1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 /* 3 * minimal stdio function definitions for NOLIBC 4 * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu> 5 */ 6 7 /* make sure to include all global symbols */ 8 #include "nolibc.h" 9 10 #ifndef _NOLIBC_STDIO_H 11 #define _NOLIBC_STDIO_H 12 13 #include "std.h" 14 #include "arch.h" 15 #include "errno.h" 16 #include "fcntl.h" 17 #include "types.h" 18 #include "sys.h" 19 #include "stdarg.h" 20 #include "stdlib.h" 21 #include "string.h" 22 #include "compiler.h" 23 24 static const char *strerror(int errnum); 25 26 #ifndef EOF 27 #define EOF (-1) 28 #endif 29 30 /* Buffering mode used by setvbuf. */ 31 #define _IOFBF 0 /* Fully buffered. */ 32 #define _IOLBF 1 /* Line buffered. */ 33 #define _IONBF 2 /* No buffering. */ 34 35 /* just define FILE as a non-empty type. The value of the pointer gives 36 * the FD: FILE=~fd for fd>=0 or NULL for fd<0. This way positive FILE 37 * are immediately identified as abnormal entries (i.e. possible copies 38 * of valid pointers to something else). 39 */ 40 typedef struct FILE { 41 char dummy[1]; 42 } FILE; 43 44 static __attribute__((unused)) FILE* const stdin = (FILE*)(intptr_t)~STDIN_FILENO; 45 static __attribute__((unused)) FILE* const stdout = (FILE*)(intptr_t)~STDOUT_FILENO; 46 static __attribute__((unused)) FILE* const stderr = (FILE*)(intptr_t)~STDERR_FILENO; 47 48 /* provides a FILE* equivalent of fd. The mode is ignored. */ 49 static __attribute__((unused)) 50 FILE *fdopen(int fd, const char *mode __attribute__((unused))) 51 { 52 if (fd < 0) { 53 SET_ERRNO(EBADF); 54 return NULL; 55 } 56 return (FILE*)(intptr_t)~fd; 57 } 58 59 static __attribute__((unused)) 60 FILE *fopen(const char *pathname, const char *mode) 61 { 62 int flags, fd; 63 64 switch (*mode) { 65 case 'r': 66 flags = O_RDONLY; 67 break; 68 case 'w': 69 flags = O_WRONLY | O_CREAT | O_TRUNC; 70 break; 71 case 'a': 72 flags = O_WRONLY | O_CREAT | O_APPEND; 73 break; 74 default: 75 SET_ERRNO(EINVAL); return NULL; 76 } 77 78 if (mode[1] == '+') 79 flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; 80 81 fd = open(pathname, flags, 0666); 82 return fdopen(fd, mode); 83 } 84 85 /* provides the fd of stream. */ 86 static __attribute__((unused)) 87 int fileno(FILE *stream) 88 { 89 intptr_t i = (intptr_t)stream; 90 91 if (i >= 0) { 92 SET_ERRNO(EBADF); 93 return -1; 94 } 95 return ~i; 96 } 97 98 /* flush a stream. */ 99 static __attribute__((unused)) 100 int fflush(FILE *stream) 101 { 102 intptr_t i = (intptr_t)stream; 103 104 /* NULL is valid here. */ 105 if (i > 0) { 106 SET_ERRNO(EBADF); 107 return -1; 108 } 109 110 /* Don't do anything, nolibc does not support buffering. */ 111 return 0; 112 } 113 114 /* flush a stream. */ 115 static __attribute__((unused)) 116 int fclose(FILE *stream) 117 { 118 intptr_t i = (intptr_t)stream; 119 120 if (i >= 0) { 121 SET_ERRNO(EBADF); 122 return -1; 123 } 124 125 if (close(~i)) 126 return EOF; 127 128 return 0; 129 } 130 131 /* getc(), fgetc(), getchar() */ 132 133 #define getc(stream) fgetc(stream) 134 135 static __attribute__((unused)) 136 int fgetc(FILE* stream) 137 { 138 unsigned char ch; 139 140 if (read(fileno(stream), &ch, 1) <= 0) 141 return EOF; 142 return ch; 143 } 144 145 static __attribute__((unused)) 146 int getchar(void) 147 { 148 return fgetc(stdin); 149 } 150 151 152 /* putc(), fputc(), putchar() */ 153 154 #define putc(c, stream) fputc(c, stream) 155 156 static __attribute__((unused)) 157 int fputc(int c, FILE* stream) 158 { 159 unsigned char ch = c; 160 161 if (write(fileno(stream), &ch, 1) <= 0) 162 return EOF; 163 return ch; 164 } 165 166 static __attribute__((unused)) 167 int putchar(int c) 168 { 169 return fputc(c, stdout); 170 } 171 172 173 /* fwrite(), fread(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */ 174 175 /* internal fwrite()-like function which only takes a size and returns 0 on 176 * success or EOF on error. It automatically retries on short writes. 177 */ 178 static __attribute__((unused)) 179 int _fwrite(const void *buf, size_t size, FILE *stream) 180 { 181 ssize_t ret; 182 int fd = fileno(stream); 183 184 while (size) { 185 ret = write(fd, buf, size); 186 if (ret <= 0) 187 return EOF; 188 size -= ret; 189 buf += ret; 190 } 191 return 0; 192 } 193 194 static __attribute__((unused)) 195 size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream) 196 { 197 size_t written; 198 199 for (written = 0; written < nmemb; written++) { 200 if (_fwrite(s, size, stream) != 0) 201 break; 202 s += size; 203 } 204 return written; 205 } 206 207 /* internal fread()-like function which only takes a size and returns 0 on 208 * success or EOF on error. It automatically retries on short reads. 209 */ 210 static __attribute__((unused)) 211 int _fread(void *buf, size_t size, FILE *stream) 212 { 213 int fd = fileno(stream); 214 ssize_t ret; 215 216 while (size) { 217 ret = read(fd, buf, size); 218 if (ret <= 0) 219 return EOF; 220 size -= ret; 221 buf += ret; 222 } 223 return 0; 224 } 225 226 static __attribute__((unused)) 227 size_t fread(void *s, size_t size, size_t nmemb, FILE *stream) 228 { 229 size_t nread; 230 231 for (nread = 0; nread < nmemb; nread++) { 232 if (_fread(s, size, stream) != 0) 233 break; 234 s += size; 235 } 236 return nread; 237 } 238 239 static __attribute__((unused)) 240 int fputs(const char *s, FILE *stream) 241 { 242 return _fwrite(s, strlen(s), stream); 243 } 244 245 static __attribute__((unused)) 246 int puts(const char *s) 247 { 248 if (fputs(s, stdout) == EOF) 249 return EOF; 250 return putchar('\n'); 251 } 252 253 254 /* fgets() */ 255 static __attribute__((unused)) 256 char *fgets(char *s, int size, FILE *stream) 257 { 258 int ofs; 259 int c; 260 261 for (ofs = 0; ofs + 1 < size;) { 262 c = fgetc(stream); 263 if (c == EOF) 264 break; 265 s[ofs++] = c; 266 if (c == '\n') 267 break; 268 } 269 if (ofs < size) 270 s[ofs] = 0; 271 return ofs ? s : NULL; 272 } 273 274 275 /* fseek */ 276 static __attribute__((unused)) 277 int fseek(FILE *stream, long offset, int whence) 278 { 279 int fd = fileno(stream); 280 off_t ret; 281 282 ret = lseek(fd, offset, whence); 283 284 /* lseek() and fseek() differ in that lseek returns the new 285 * position or -1, fseek() returns either 0 or -1. 286 */ 287 if (ret >= 0) 288 return 0; 289 290 return -1; 291 } 292 293 294 /* printf(). Supports most of the normal integer and string formats. 295 * - %[#0-+ ][width|*[.precision|*}][{l,t,z,ll,L,j,q}]{c,d,i,u,o,x,X,p,s,m,%} 296 * - %% generates a single % 297 * - %m outputs strerror(errno). 298 * - %X outputs a..f the same as %x. 299 * - No support for floating point or wide characters. 300 * - Invalid formats are copied to the output buffer. 301 * 302 * Called by vfprintf() and snprintf() to do the actual formatting. 303 * The callers provide a callback function to save the formatted data. 304 * The callback function is called multiple times: 305 * - for each group of literal characters in the format string. 306 * - for field padding. 307 * - for each conversion specifier. 308 * - with (NULL, 0) at the end of the __nolibc_printf. 309 * If the callback returns non-zero __nolibc_printf() immediately returns -1. 310 */ 311 312 typedef int (*__nolibc_printf_cb)(void *state, const char *buf, size_t size); 313 314 /* This code uses 'flag' variables that are indexed by the low 6 bits 315 * of characters to optimise checks for multiple characters. 316 * 317 * _NOLIBC_PF_FLAGS_CONTAIN(flags, 'a', 'b'. ...) 318 * returns non-zero if the bit for any of the specified characters is set. 319 * 320 * _NOLIBC_PF_CHAR_IS_ONE_OF(ch, 'a', 'b'. ...) 321 * returns the flag bit for ch if it is one of the specified characters. 322 * All the characters must be in the same 32 character block (non-alphabetic, 323 * upper case, or lower case) of the ASCII character set. 324 */ 325 #define _NOLIBC_PF_FLAG(ch) (1u << ((ch) & 0x1f)) 326 #define _NOLIBC_PF_FLAG_NZ(ch) ((ch) ? _NOLIBC_PF_FLAG(ch) : 0) 327 #define _NOLIBC_PF_FLAG8(cmp_1, cmp_2, cmp_3, cmp_4, cmp_5, cmp_6, cmp_7, cmp_8, ...) \ 328 (_NOLIBC_PF_FLAG_NZ(cmp_1) | _NOLIBC_PF_FLAG_NZ(cmp_2) | \ 329 _NOLIBC_PF_FLAG_NZ(cmp_3) | _NOLIBC_PF_FLAG_NZ(cmp_4) | \ 330 _NOLIBC_PF_FLAG_NZ(cmp_5) | _NOLIBC_PF_FLAG_NZ(cmp_6) | \ 331 _NOLIBC_PF_FLAG_NZ(cmp_7) | _NOLIBC_PF_FLAG_NZ(cmp_8)) 332 #define _NOLIBC_PF_FLAGS_CONTAIN(flags, ...) \ 333 ((flags) & _NOLIBC_PF_FLAG8(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0)) 334 #define _NOLIBC_PF_CHAR_IS_ONE_OF(ch, cmp_1, ...) \ 335 ((unsigned int)(ch) - (cmp_1 & 0xe0) > 0x1f ? 0 : \ 336 _NOLIBC_PF_FLAGS_CONTAIN(_NOLIBC_PF_FLAG(ch), cmp_1, __VA_ARGS__)) 337 338 static __attribute__((unused, format(printf, 3, 0))) 339 int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list args) 340 { 341 char ch; 342 unsigned long long v; 343 long long signed_v; 344 int written, width, precision, len; 345 unsigned int flags, ch_flag; 346 char outbuf[2 + 31 + 22 + 1]; 347 char *out; 348 const char *outstr; 349 unsigned int sign_prefix; 350 int got_width; 351 352 written = 0; 353 while (1) { 354 outstr = fmt; 355 ch = *fmt++; 356 if (!ch) 357 break; 358 359 width = 0; 360 flags = 0; 361 if (ch != '%') { 362 while (*fmt && *fmt != '%') 363 fmt++; 364 /* Output characters from the format string. */ 365 len = fmt - outstr; 366 goto do_output; 367 } 368 369 /* we're in a format sequence */ 370 371 /* Conversion flag characters */ 372 while (1) { 373 ch = *fmt++; 374 ch_flag = _NOLIBC_PF_CHAR_IS_ONE_OF(ch, ' ', '#', '+', '-', '0'); 375 if (!ch_flag) 376 break; 377 flags |= ch_flag; 378 } 379 380 /* Width and precision */ 381 for (got_width = 0;; ch = *fmt++) { 382 if (ch == '*') { 383 precision = va_arg(args, int); 384 ch = *fmt++; 385 } else { 386 for (precision = 0; ch >= '0' && ch <= '9'; ch = *fmt++) 387 precision = precision * 10 + (ch - '0'); 388 } 389 if (got_width) 390 break; 391 width = precision; 392 if (ch != '.') { 393 /* Default precision for strings */ 394 precision = -1; 395 break; 396 } 397 got_width = 1; 398 } 399 /* A negative width (e.g. from "%*s") requests left justify. */ 400 if (width < 0) { 401 width = -width; 402 flags |= _NOLIBC_PF_FLAG('-'); 403 } 404 405 /* Length modifier. 406 * They miss the conversion flags characters " #+-0" so can go into flags. 407 * Change both L and ll to j (all always 64bit). 408 */ 409 if (ch == 'L') 410 ch = 'j'; 411 ch_flag = _NOLIBC_PF_CHAR_IS_ONE_OF(ch, 'l', 't', 'z', 'j', 'q'); 412 if (ch_flag != 0) { 413 if (ch == 'l' && fmt[0] == 'l') { 414 fmt++; 415 ch_flag = _NOLIBC_PF_FLAG('j'); 416 } 417 flags |= ch_flag; 418 ch = *fmt++; 419 } 420 421 /* Conversion specifiers. */ 422 423 /* Numeric and pointer conversion specifiers. 424 * 425 * Use an explicit bound check (rather than _NOLIBC_PF_CHAR_IS_ONE_OF()) 426 * so that 'X' can be allowed through. 427 * 'X' gets treated and 'x' because _NOLIBC_PF_FLAG() returns the same 428 * value for both. 429 * 430 * We need to check for "%p" or "%#x" later, merging here gives better code. 431 * But '#' collides with 'c' so shift right. 432 */ 433 ch_flag = _NOLIBC_PF_FLAG(ch) | (flags & _NOLIBC_PF_FLAG('#')) >> 1; 434 if (((ch >= 'a' && ch <= 'z') || ch == 'X') && 435 _NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'c', 'd', 'i', 'u', 'o', 'x', 'p', 's')) { 436 /* 'long' is needed for pointer/string conversions and ltz lengths. 437 * A single test can be used provided 'p' (the same bit as '0') 438 * is masked from flags. 439 */ 440 if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag | (flags & ~_NOLIBC_PF_FLAG('p')), 441 'p', 's', 'l', 't', 'z')) { 442 v = va_arg(args, unsigned long); 443 signed_v = (long)v; 444 } else if (_NOLIBC_PF_FLAGS_CONTAIN(flags, 'j', 'q')) { 445 v = va_arg(args, unsigned long long); 446 signed_v = v; 447 } else { 448 v = va_arg(args, unsigned int); 449 signed_v = (int)v; 450 } 451 452 if (ch == 'c') { 453 /* "%c" - single character. */ 454 outbuf[0] = v; 455 len = 1; 456 outstr = outbuf; 457 goto do_output; 458 } 459 460 if (ch == 's') { 461 /* "%s" - character string. */ 462 outstr = (const char *)(uintptr_t)v; 463 if (!outstr) { 464 outstr = "(null)"; 465 /* Match glibc, nothing output if precision too small */ 466 len = precision < 0 || precision >= 6 ? 6 : 0; 467 goto do_output; 468 } 469 goto do_strlen_output; 470 } 471 472 /* The 'sign_prefix' can be zero, one or two ("0x") characters. 473 * Prepended least significant byte first stopping on a zero byte. 474 */ 475 sign_prefix = 0; 476 477 if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'd', 'i')) { 478 /* "%d" and "%i" - signed decimal numbers. */ 479 if (signed_v < 0) { 480 sign_prefix = '-'; 481 v = -(signed_v + 1); 482 v++; 483 } else if (_NOLIBC_PF_FLAGS_CONTAIN(flags, '+')) { 484 sign_prefix = '+'; 485 } else if (_NOLIBC_PF_FLAGS_CONTAIN(flags, ' ')) { 486 sign_prefix = ' '; 487 } 488 } else { 489 /* "#o" requires that the output always starts with a '0'. 490 * This needs another check after any zero padding to avoid 491 * adding an extra leading '0'. 492 */ 493 if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'o') && 494 _NOLIBC_PF_FLAGS_CONTAIN(ch_flag, '#' - 1)) 495 sign_prefix = '0'; 496 } 497 498 /* The value is converted offset into the buffer so that 499 * 31 zero pad characters and the sign/prefix can be added in front. 500 * The longest digit string is 22 + 1 for octal conversions. 501 */ 502 out = outbuf + 2 + 31; 503 504 if (v == 0) { 505 /* There are special rules for zero. */ 506 if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'p')) { 507 /* "%p" match glibc, precision is ignored */ 508 outstr = "(nil)"; 509 len = 5; 510 goto do_output; 511 } 512 if (!precision) { 513 /* Explicit %nn.0d, no digits output (except for %#.0o) */ 514 len = 0; 515 goto prepend_sign; 516 } 517 /* All other formats (including "%#x") just output "0". */ 518 out[0] = '0'; 519 len = 1; 520 } else { 521 /* Convert the number to ascii in the required base. */ 522 unsigned long long recip; 523 unsigned int base; 524 if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'd', 'i', 'u')) { 525 base = 10; 526 recip = _NOLIBC_U64TOA_RECIP(10); 527 } else if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'o')) { 528 base = 8; 529 recip = _NOLIBC_U64TOA_RECIP(8); 530 } else { 531 base = 16; 532 recip = _NOLIBC_U64TOA_RECIP(16); 533 if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'p', '#' - 1)) { 534 /* "%p" and "%#x" need "0x" prepending. */ 535 sign_prefix = '0' << 8 | 'x'; 536 } 537 } 538 len = _nolibc_u64toa_base(v, out, base, recip); 539 } 540 541 /* Add zero padding */ 542 if (precision < 0) { 543 /* No explicit precision (or negative from "%.*s"). */ 544 if (!_NOLIBC_PF_FLAGS_CONTAIN(flags, '0')) 545 goto no_zero_padding; 546 if (_NOLIBC_PF_FLAGS_CONTAIN(flags, '-')) 547 /* Left justify overrides zero pad */ 548 goto no_zero_padding; 549 /* eg "%05d", Zero pad to field width less sign. 550 * Note that precision can end up negative so all 551 * the variables have to be 'signed int'. 552 */ 553 precision = width; 554 if (sign_prefix) { 555 precision--; 556 if (sign_prefix >= 256) 557 precision--; 558 } 559 } 560 if (precision > 31) 561 /* Don't run off the start of outbuf[], arbitrary limit 562 * longer than the longest number field. */ 563 precision = 31; 564 for (; len < precision; len++) { 565 /* Stop gcc generating horrid code and memset(). */ 566 _NOLIBC_OPTIMIZER_HIDE_VAR(len); 567 *--out = '0'; 568 } 569 no_zero_padding: 570 571 /* %#o has set sign_prefix to '0', but we don't want so add an extra 572 * leading zero here. 573 * Since the only other byte values of sign_prefix are ' ', '+' and '-' 574 * it is enough to check that out[] doesn't already start with sign_prefix. 575 */ 576 if (sign_prefix - *out) { 577 prepend_sign: 578 /* Add the 0, 1 or 2 ("0x") sign/prefix characters at the front. */ 579 for (; sign_prefix; sign_prefix >>= 8) { 580 /* Force gcc to increment len inside the loop. */ 581 _NOLIBC_OPTIMIZER_HIDE_VAR(len); 582 len++; 583 *--out = sign_prefix; 584 } 585 } 586 outstr = out; 587 goto do_output; 588 } 589 590 if (ch == 'm') { 591 #ifdef NOLIBC_IGNORE_ERRNO 592 outstr = "unknown error"; 593 #else 594 outstr = strerror(errno); 595 #endif /* NOLIBC_IGNORE_ERRNO */ 596 goto do_strlen_output; 597 } 598 599 if (ch != '%') { 600 /* Invalid format: back up to output the format characters */ 601 fmt = outstr + 1; 602 /* and output a '%' now. */ 603 } 604 /* %% is documented as a 'conversion specifier'. 605 * Any flags, precision or length modifier are ignored. 606 */ 607 len = 1; 608 width = 0; 609 outstr = fmt - 1; 610 goto do_output; 611 612 do_strlen_output: 613 /* Open coded strnlen() (slightly smaller). */ 614 for (len = 0; precision < 0 || len < precision; len++) 615 if (!outstr[len]) 616 break; 617 618 do_output: 619 written += len; 620 621 /* Stop gcc back-merging this code into one of the conditionals above. */ 622 _NOLIBC_OPTIMIZER_HIDE_VAR(len); 623 624 /* Output the characters on the required side of any padding. */ 625 width -= len; 626 flags = _NOLIBC_PF_FLAGS_CONTAIN(flags, '-'); 627 if (flags && cb(state, outstr, len) != 0) 628 return -1; 629 while (width > 0) { 630 /* Output pad in 16 byte blocks with the small block first. */ 631 int pad_len = ((width - 1) & 15) + 1; 632 width -= pad_len; 633 written += pad_len; 634 if (cb(state, " ", pad_len) != 0) 635 return -1; 636 } 637 if (!flags && cb(state, outstr, len) != 0) 638 return -1; 639 } 640 641 /* Request a final '\0' be added to the snprintf() output. 642 * This may be the only call of the cb() function. 643 */ 644 if (cb(state, NULL, 0) != 0) 645 return -1; 646 647 return written; 648 } 649 650 static int __nolibc_fprintf_cb(void *stream, const char *buf, size_t size) 651 { 652 return _fwrite(buf, size, stream); 653 } 654 655 static __attribute__((unused, format(printf, 2, 0))) 656 int vfprintf(FILE *stream, const char *fmt, va_list args) 657 { 658 return __nolibc_printf(__nolibc_fprintf_cb, stream, fmt, args); 659 } 660 661 static __attribute__((unused, format(printf, 1, 0))) 662 int vprintf(const char *fmt, va_list args) 663 { 664 return vfprintf(stdout, fmt, args); 665 } 666 667 static __attribute__((unused, format(printf, 2, 3))) 668 int fprintf(FILE *stream, const char *fmt, ...) 669 { 670 va_list args; 671 int ret; 672 673 va_start(args, fmt); 674 ret = vfprintf(stream, fmt, args); 675 va_end(args); 676 return ret; 677 } 678 679 static __attribute__((unused, format(printf, 1, 2))) 680 int printf(const char *fmt, ...) 681 { 682 va_list args; 683 int ret; 684 685 va_start(args, fmt); 686 ret = vfprintf(stdout, fmt, args); 687 va_end(args); 688 return ret; 689 } 690 691 static __attribute__((unused, format(printf, 2, 0))) 692 int vdprintf(int fd, const char *fmt, va_list args) 693 { 694 FILE *stream; 695 696 stream = fdopen(fd, NULL); 697 if (!stream) 698 return -1; 699 /* Technically 'stream' is leaked, but as it's only a wrapper around 'fd' that is fine */ 700 return vfprintf(stream, fmt, args); 701 } 702 703 static __attribute__((unused, format(printf, 2, 3))) 704 int dprintf(int fd, const char *fmt, ...) 705 { 706 va_list args; 707 int ret; 708 709 va_start(args, fmt); 710 ret = vdprintf(fd, fmt, args); 711 va_end(args); 712 713 return ret; 714 } 715 716 struct __nolibc_sprintf_cb_state { 717 char *buf; 718 size_t space; 719 }; 720 721 static int __nolibc_sprintf_cb(void *v_state, const char *buf, size_t size) 722 { 723 struct __nolibc_sprintf_cb_state *state = v_state; 724 size_t space = state->space; 725 char *tgt; 726 727 /* Truncate the request to fit in the output buffer space. 728 * The last byte is reserved for the terminating '\0'. 729 * state->space can only be zero for snprintf(NULL, 0, fmt, args) 730 * so this normally lets through calls with 'size == 0'. 731 */ 732 if (size >= space) { 733 if (space <= 1) 734 return 0; 735 size = space - 1; 736 } 737 tgt = state->buf; 738 739 /* __nolibc_printf() ends with cb(state, NULL, 0) to request the output 740 * buffer be '\0' terminated. 741 * That will be the only cb() call for, eg, snprintf(buf, sz, ""). 742 * Zero lengths can occur at other times (eg "%s" for an empty string). 743 * Unconditionally write the '\0' byte to reduce code size, it is 744 * normally overwritten by the data being output. 745 * There is no point adding a '\0' after copied data - there is always 746 * another call. 747 */ 748 *tgt = '\0'; 749 if (size) { 750 state->space = space - size; 751 state->buf = tgt + size; 752 memcpy(tgt, buf, size); 753 } 754 755 return 0; 756 } 757 758 static __attribute__((unused, format(printf, 3, 0))) 759 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) 760 { 761 struct __nolibc_sprintf_cb_state state = { .buf = buf, .space = size }; 762 763 return __nolibc_printf(__nolibc_sprintf_cb, &state, fmt, args); 764 } 765 766 static __attribute__((unused, format(printf, 3, 4))) 767 int snprintf(char *buf, size_t size, const char *fmt, ...) 768 { 769 va_list args; 770 int ret; 771 772 va_start(args, fmt); 773 ret = vsnprintf(buf, size, fmt, args); 774 va_end(args); 775 776 return ret; 777 } 778 779 static __attribute__((unused, format(printf, 2, 0))) 780 int vsprintf(char *buf, const char *fmt, va_list args) 781 { 782 return vsnprintf(buf, SIZE_MAX, fmt, args); 783 } 784 785 static __attribute__((unused, format(printf, 2, 3))) 786 int sprintf(char *buf, const char *fmt, ...) 787 { 788 va_list args; 789 int ret; 790 791 va_start(args, fmt); 792 ret = vsprintf(buf, fmt, args); 793 va_end(args); 794 795 return ret; 796 } 797 798 static __attribute__((unused, format(printf, 2, 0))) 799 int __nolibc_vasprintf(char **strp, const char *fmt, va_list args1, va_list args2) 800 { 801 int len1, len2; 802 char *buf; 803 804 len1 = vsnprintf(NULL, 0, fmt, args1); 805 if (len1 < 0) 806 return -1; 807 808 buf = malloc(len1 + 1); 809 if (!buf) 810 return -1; 811 812 len2 = vsnprintf(buf, len1 + 1, fmt, args2); 813 if (len2 < 0) { 814 free(buf); 815 return -1; 816 } 817 818 *strp = buf; 819 return len1; 820 } 821 822 static __attribute__((unused, format(printf, 2, 0))) 823 int vasprintf(char **strp, const char *fmt, va_list args) 824 { 825 va_list args2; 826 int ret; 827 828 va_copy(args2, args); 829 ret = __nolibc_vasprintf(strp, fmt, args, args2); 830 va_end(args2); 831 832 return ret; 833 } 834 835 static __attribute__((unused, format(printf, 2, 3))) 836 int asprintf(char **strp, const char *fmt, ...) 837 { 838 va_list args; 839 int ret; 840 841 va_start(args, fmt); 842 ret = vasprintf(strp, fmt, args); 843 va_end(args); 844 845 return ret; 846 } 847 848 static __attribute__((unused)) 849 int vsscanf(const char *str, const char *format, va_list args) 850 { 851 uintmax_t uval; 852 intmax_t ival; 853 int base; 854 char *endptr; 855 int matches; 856 int lpref; 857 858 matches = 0; 859 860 while (1) { 861 if (*format == '%') { 862 /* start of pattern */ 863 lpref = 0; 864 format++; 865 866 if (*format == 'l') { 867 /* same as in printf() */ 868 lpref = 1; 869 format++; 870 if (*format == 'l') { 871 lpref = 2; 872 format++; 873 } 874 } 875 876 if (*format == '%') { 877 /* literal % */ 878 if ('%' != *str) 879 goto done; 880 str++; 881 format++; 882 continue; 883 } else if (*format == 'd') { 884 ival = strtoll(str, &endptr, 10); 885 if (lpref == 0) 886 *va_arg(args, int *) = ival; 887 else if (lpref == 1) 888 *va_arg(args, long *) = ival; 889 else if (lpref == 2) 890 *va_arg(args, long long *) = ival; 891 } else if (*format == 'u' || *format == 'x' || *format == 'X') { 892 base = *format == 'u' ? 10 : 16; 893 uval = strtoull(str, &endptr, base); 894 if (lpref == 0) 895 *va_arg(args, unsigned int *) = uval; 896 else if (lpref == 1) 897 *va_arg(args, unsigned long *) = uval; 898 else if (lpref == 2) 899 *va_arg(args, unsigned long long *) = uval; 900 } else if (*format == 'p') { 901 *va_arg(args, void **) = (void *)strtoul(str, &endptr, 16); 902 } else { 903 SET_ERRNO(EILSEQ); 904 goto done; 905 } 906 907 format++; 908 str = endptr; 909 matches++; 910 911 } else if (*format == '\0') { 912 goto done; 913 } else if (isspace(*format)) { 914 /* skip spaces in format and str */ 915 while (isspace(*format)) 916 format++; 917 while (isspace(*str)) 918 str++; 919 } else if (*format == *str) { 920 /* literal match */ 921 format++; 922 str++; 923 } else { 924 if (!matches) 925 matches = EOF; 926 goto done; 927 } 928 } 929 930 done: 931 return matches; 932 } 933 934 static __attribute__((unused, format(scanf, 2, 3))) 935 int sscanf(const char *str, const char *format, ...) 936 { 937 va_list args; 938 int ret; 939 940 va_start(args, format); 941 ret = vsscanf(str, format, args); 942 va_end(args); 943 return ret; 944 } 945 946 static __attribute__((unused)) 947 void perror(const char *msg) 948 { 949 #ifdef NOLIBC_IGNORE_ERRNO 950 fprintf(stderr, "%s%sunknown error\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : ""); 951 #else 952 fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno); 953 #endif 954 } 955 956 static __attribute__((unused)) 957 int setvbuf(FILE *stream __attribute__((unused)), 958 char *buf __attribute__((unused)), 959 int mode, 960 size_t size __attribute__((unused))) 961 { 962 /* 963 * nolibc does not support buffering so this is a nop. Just check mode 964 * is valid as required by the spec. 965 */ 966 switch (mode) { 967 case _IOFBF: 968 case _IOLBF: 969 case _IONBF: 970 break; 971 default: 972 return EOF; 973 } 974 975 return 0; 976 } 977 978 static __attribute__((unused)) 979 int strerror_r(int errnum, char *buf, size_t buflen) 980 { 981 if (buflen < 18) 982 return ERANGE; 983 984 __builtin_memcpy(buf, "errno=", 6); 985 i64toa_r(errnum, buf + 6); 986 return 0; 987 } 988 989 static __attribute__((unused)) 990 const char *strerror(int errnum) 991 { 992 static char buf[18]; 993 char *b = buf; 994 995 /* Force gcc to use 'register offset' to access buf[]. */ 996 _NOLIBC_OPTIMIZER_HIDE_VAR(b); 997 998 /* Use strerror_r() to avoid having the only .data in small programs. */ 999 strerror_r(errnum, b, sizeof(buf)); 1000 1001 return b; 1002 } 1003 1004 #endif /* _NOLIBC_STDIO_H */ 1005