stdio.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  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. /* make sure to include all global symbols */
  7. #include "nolibc.h"
  8. #ifndef _NOLIBC_STDIO_H
  9. #define _NOLIBC_STDIO_H
  10. #include "std.h"
  11. #include "arch.h"
  12. #include "errno.h"
  13. #include "fcntl.h"
  14. #include "types.h"
  15. #include "sys.h"
  16. #include "stdarg.h"
  17. #include "stdlib.h"
  18. #include "string.h"
  19. #include "compiler.h"
  20. static const char *strerror(int errnum);
  21. #ifndef EOF
  22. #define EOF (-1)
  23. #endif
  24. /* Buffering mode used by setvbuf. */
  25. #define _IOFBF 0 /* Fully buffered. */
  26. #define _IOLBF 1 /* Line buffered. */
  27. #define _IONBF 2 /* No buffering. */
  28. /* just define FILE as a non-empty type. The value of the pointer gives
  29. * the FD: FILE=~fd for fd>=0 or NULL for fd<0. This way positive FILE
  30. * are immediately identified as abnormal entries (i.e. possible copies
  31. * of valid pointers to something else).
  32. */
  33. typedef struct FILE {
  34. char dummy[1];
  35. } FILE;
  36. static __attribute__((unused)) FILE* const stdin = (FILE*)(intptr_t)~STDIN_FILENO;
  37. static __attribute__((unused)) FILE* const stdout = (FILE*)(intptr_t)~STDOUT_FILENO;
  38. static __attribute__((unused)) FILE* const stderr = (FILE*)(intptr_t)~STDERR_FILENO;
  39. /* provides a FILE* equivalent of fd. The mode is ignored. */
  40. static __attribute__((unused))
  41. FILE *fdopen(int fd, const char *mode __attribute__((unused)))
  42. {
  43. if (fd < 0) {
  44. SET_ERRNO(EBADF);
  45. return NULL;
  46. }
  47. return (FILE*)(intptr_t)~fd;
  48. }
  49. static __attribute__((unused))
  50. FILE *fopen(const char *pathname, const char *mode)
  51. {
  52. int flags, fd;
  53. switch (*mode) {
  54. case 'r':
  55. flags = O_RDONLY;
  56. break;
  57. case 'w':
  58. flags = O_WRONLY | O_CREAT | O_TRUNC;
  59. break;
  60. case 'a':
  61. flags = O_WRONLY | O_CREAT | O_APPEND;
  62. break;
  63. default:
  64. SET_ERRNO(EINVAL); return NULL;
  65. }
  66. if (mode[1] == '+')
  67. flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
  68. fd = open(pathname, flags, 0666);
  69. return fdopen(fd, mode);
  70. }
  71. /* provides the fd of stream. */
  72. static __attribute__((unused))
  73. int fileno(FILE *stream)
  74. {
  75. intptr_t i = (intptr_t)stream;
  76. if (i >= 0) {
  77. SET_ERRNO(EBADF);
  78. return -1;
  79. }
  80. return ~i;
  81. }
  82. /* flush a stream. */
  83. static __attribute__((unused))
  84. int fflush(FILE *stream)
  85. {
  86. intptr_t i = (intptr_t)stream;
  87. /* NULL is valid here. */
  88. if (i > 0) {
  89. SET_ERRNO(EBADF);
  90. return -1;
  91. }
  92. /* Don't do anything, nolibc does not support buffering. */
  93. return 0;
  94. }
  95. /* flush a stream. */
  96. static __attribute__((unused))
  97. int fclose(FILE *stream)
  98. {
  99. intptr_t i = (intptr_t)stream;
  100. if (i >= 0) {
  101. SET_ERRNO(EBADF);
  102. return -1;
  103. }
  104. if (close(~i))
  105. return EOF;
  106. return 0;
  107. }
  108. /* getc(), fgetc(), getchar() */
  109. #define getc(stream) fgetc(stream)
  110. static __attribute__((unused))
  111. int fgetc(FILE* stream)
  112. {
  113. unsigned char ch;
  114. if (read(fileno(stream), &ch, 1) <= 0)
  115. return EOF;
  116. return ch;
  117. }
  118. static __attribute__((unused))
  119. int getchar(void)
  120. {
  121. return fgetc(stdin);
  122. }
  123. /* putc(), fputc(), putchar() */
  124. #define putc(c, stream) fputc(c, stream)
  125. static __attribute__((unused))
  126. int fputc(int c, FILE* stream)
  127. {
  128. unsigned char ch = c;
  129. if (write(fileno(stream), &ch, 1) <= 0)
  130. return EOF;
  131. return ch;
  132. }
  133. static __attribute__((unused))
  134. int putchar(int c)
  135. {
  136. return fputc(c, stdout);
  137. }
  138. /* fwrite(), fread(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
  139. /* internal fwrite()-like function which only takes a size and returns 0 on
  140. * success or EOF on error. It automatically retries on short writes.
  141. */
  142. static __attribute__((unused))
  143. int _fwrite(const void *buf, size_t size, FILE *stream)
  144. {
  145. ssize_t ret;
  146. int fd = fileno(stream);
  147. while (size) {
  148. ret = write(fd, buf, size);
  149. if (ret <= 0)
  150. return EOF;
  151. size -= ret;
  152. buf += ret;
  153. }
  154. return 0;
  155. }
  156. static __attribute__((unused))
  157. size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream)
  158. {
  159. size_t written;
  160. for (written = 0; written < nmemb; written++) {
  161. if (_fwrite(s, size, stream) != 0)
  162. break;
  163. s += size;
  164. }
  165. return written;
  166. }
  167. /* internal fread()-like function which only takes a size and returns 0 on
  168. * success or EOF on error. It automatically retries on short reads.
  169. */
  170. static __attribute__((unused))
  171. int _fread(void *buf, size_t size, FILE *stream)
  172. {
  173. int fd = fileno(stream);
  174. ssize_t ret;
  175. while (size) {
  176. ret = read(fd, buf, size);
  177. if (ret <= 0)
  178. return EOF;
  179. size -= ret;
  180. buf += ret;
  181. }
  182. return 0;
  183. }
  184. static __attribute__((unused))
  185. size_t fread(void *s, size_t size, size_t nmemb, FILE *stream)
  186. {
  187. size_t nread;
  188. for (nread = 0; nread < nmemb; nread++) {
  189. if (_fread(s, size, stream) != 0)
  190. break;
  191. s += size;
  192. }
  193. return nread;
  194. }
  195. static __attribute__((unused))
  196. int fputs(const char *s, FILE *stream)
  197. {
  198. return _fwrite(s, strlen(s), stream);
  199. }
  200. static __attribute__((unused))
  201. int puts(const char *s)
  202. {
  203. if (fputs(s, stdout) == EOF)
  204. return EOF;
  205. return putchar('\n');
  206. }
  207. /* fgets() */
  208. static __attribute__((unused))
  209. char *fgets(char *s, int size, FILE *stream)
  210. {
  211. int ofs;
  212. int c;
  213. for (ofs = 0; ofs + 1 < size;) {
  214. c = fgetc(stream);
  215. if (c == EOF)
  216. break;
  217. s[ofs++] = c;
  218. if (c == '\n')
  219. break;
  220. }
  221. if (ofs < size)
  222. s[ofs] = 0;
  223. return ofs ? s : NULL;
  224. }
  225. /* fseek */
  226. static __attribute__((unused))
  227. int fseek(FILE *stream, long offset, int whence)
  228. {
  229. int fd = fileno(stream);
  230. off_t ret;
  231. ret = lseek(fd, offset, whence);
  232. /* lseek() and fseek() differ in that lseek returns the new
  233. * position or -1, fseek() returns either 0 or -1.
  234. */
  235. if (ret >= 0)
  236. return 0;
  237. return -1;
  238. }
  239. /* minimal printf(). It supports the following formats:
  240. * - %[l*]{d,u,c,x,p}
  241. * - %s
  242. * - unknown modifiers are ignored.
  243. */
  244. typedef int (*__nolibc_printf_cb)(intptr_t state, const char *buf, size_t size);
  245. static __attribute__((unused, format(printf, 4, 0)))
  246. int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char *fmt, va_list args)
  247. {
  248. char escape, lpref, c;
  249. unsigned long long v;
  250. unsigned int written, width;
  251. size_t len, ofs, w;
  252. char tmpbuf[21];
  253. const char *outstr;
  254. written = ofs = escape = lpref = 0;
  255. while (1) {
  256. c = fmt[ofs++];
  257. width = 0;
  258. if (escape) {
  259. /* we're in an escape sequence, ofs == 1 */
  260. escape = 0;
  261. /* width */
  262. while (c >= '0' && c <= '9') {
  263. width *= 10;
  264. width += c - '0';
  265. c = fmt[ofs++];
  266. }
  267. if (c == 'c' || c == 'd' || c == 'u' || c == 'x' || c == 'p') {
  268. char *out = tmpbuf;
  269. if (c == 'p')
  270. v = va_arg(args, unsigned long);
  271. else if (lpref) {
  272. if (lpref > 1)
  273. v = va_arg(args, unsigned long long);
  274. else
  275. v = va_arg(args, unsigned long);
  276. } else
  277. v = va_arg(args, unsigned int);
  278. if (c == 'd') {
  279. /* sign-extend the value */
  280. if (lpref == 0)
  281. v = (long long)(int)v;
  282. else if (lpref == 1)
  283. v = (long long)(long)v;
  284. }
  285. switch (c) {
  286. case 'c':
  287. out[0] = v;
  288. out[1] = 0;
  289. break;
  290. case 'd':
  291. i64toa_r(v, out);
  292. break;
  293. case 'u':
  294. u64toa_r(v, out);
  295. break;
  296. case 'p':
  297. *(out++) = '0';
  298. *(out++) = 'x';
  299. __nolibc_fallthrough;
  300. default: /* 'x' and 'p' above */
  301. u64toh_r(v, out);
  302. break;
  303. }
  304. outstr = tmpbuf;
  305. }
  306. else if (c == 's') {
  307. outstr = va_arg(args, char *);
  308. if (!outstr)
  309. outstr="(null)";
  310. }
  311. else if (c == 'm') {
  312. #ifdef NOLIBC_IGNORE_ERRNO
  313. outstr = "unknown error";
  314. #else
  315. outstr = strerror(errno);
  316. #endif /* NOLIBC_IGNORE_ERRNO */
  317. }
  318. else if (c == '%') {
  319. /* queue it verbatim */
  320. continue;
  321. }
  322. else {
  323. /* modifiers or final 0 */
  324. if (c == 'l') {
  325. /* long format prefix, maintain the escape */
  326. lpref++;
  327. } else if (c == 'j') {
  328. lpref = 2;
  329. }
  330. escape = 1;
  331. goto do_escape;
  332. }
  333. len = strlen(outstr);
  334. goto flush_str;
  335. }
  336. /* not an escape sequence */
  337. if (c == 0 || c == '%') {
  338. /* flush pending data on escape or end */
  339. escape = 1;
  340. lpref = 0;
  341. outstr = fmt;
  342. len = ofs - 1;
  343. flush_str:
  344. if (n) {
  345. w = len < n ? len : n;
  346. n -= w;
  347. while (width-- > w) {
  348. if (cb(state, " ", 1) != 0)
  349. return -1;
  350. written += 1;
  351. }
  352. if (cb(state, outstr, w) != 0)
  353. return -1;
  354. }
  355. written += len;
  356. do_escape:
  357. if (c == 0)
  358. break;
  359. fmt += ofs;
  360. ofs = 0;
  361. continue;
  362. }
  363. /* literal char, just queue it */
  364. }
  365. return written;
  366. }
  367. static int __nolibc_fprintf_cb(intptr_t state, const char *buf, size_t size)
  368. {
  369. return _fwrite(buf, size, (FILE *)state);
  370. }
  371. static __attribute__((unused, format(printf, 2, 0)))
  372. int vfprintf(FILE *stream, const char *fmt, va_list args)
  373. {
  374. return __nolibc_printf(__nolibc_fprintf_cb, (intptr_t)stream, SIZE_MAX, fmt, args);
  375. }
  376. static __attribute__((unused, format(printf, 1, 0)))
  377. int vprintf(const char *fmt, va_list args)
  378. {
  379. return vfprintf(stdout, fmt, args);
  380. }
  381. static __attribute__((unused, format(printf, 2, 3)))
  382. int fprintf(FILE *stream, const char *fmt, ...)
  383. {
  384. va_list args;
  385. int ret;
  386. va_start(args, fmt);
  387. ret = vfprintf(stream, fmt, args);
  388. va_end(args);
  389. return ret;
  390. }
  391. static __attribute__((unused, format(printf, 1, 2)))
  392. int printf(const char *fmt, ...)
  393. {
  394. va_list args;
  395. int ret;
  396. va_start(args, fmt);
  397. ret = vfprintf(stdout, fmt, args);
  398. va_end(args);
  399. return ret;
  400. }
  401. static __attribute__((unused, format(printf, 2, 0)))
  402. int vdprintf(int fd, const char *fmt, va_list args)
  403. {
  404. FILE *stream;
  405. stream = fdopen(fd, NULL);
  406. if (!stream)
  407. return -1;
  408. /* Technically 'stream' is leaked, but as it's only a wrapper around 'fd' that is fine */
  409. return vfprintf(stream, fmt, args);
  410. }
  411. static __attribute__((unused, format(printf, 2, 3)))
  412. int dprintf(int fd, const char *fmt, ...)
  413. {
  414. va_list args;
  415. int ret;
  416. va_start(args, fmt);
  417. ret = vdprintf(fd, fmt, args);
  418. va_end(args);
  419. return ret;
  420. }
  421. static int __nolibc_sprintf_cb(intptr_t _state, const char *buf, size_t size)
  422. {
  423. char **state = (char **)_state;
  424. memcpy(*state, buf, size);
  425. *state += size;
  426. return 0;
  427. }
  428. static __attribute__((unused, format(printf, 3, 0)))
  429. int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
  430. {
  431. char *state = buf;
  432. int ret;
  433. ret = __nolibc_printf(__nolibc_sprintf_cb, (intptr_t)&state, size, fmt, args);
  434. if (ret < 0)
  435. return ret;
  436. buf[(size_t)ret < size ? (size_t)ret : size - 1] = '\0';
  437. return ret;
  438. }
  439. static __attribute__((unused, format(printf, 3, 4)))
  440. int snprintf(char *buf, size_t size, const char *fmt, ...)
  441. {
  442. va_list args;
  443. int ret;
  444. va_start(args, fmt);
  445. ret = vsnprintf(buf, size, fmt, args);
  446. va_end(args);
  447. return ret;
  448. }
  449. static __attribute__((unused, format(printf, 2, 0)))
  450. int vsprintf(char *buf, const char *fmt, va_list args)
  451. {
  452. return vsnprintf(buf, SIZE_MAX, fmt, args);
  453. }
  454. static __attribute__((unused, format(printf, 2, 3)))
  455. int sprintf(char *buf, const char *fmt, ...)
  456. {
  457. va_list args;
  458. int ret;
  459. va_start(args, fmt);
  460. ret = vsprintf(buf, fmt, args);
  461. va_end(args);
  462. return ret;
  463. }
  464. static __attribute__((unused))
  465. int vsscanf(const char *str, const char *format, va_list args)
  466. {
  467. uintmax_t uval;
  468. intmax_t ival;
  469. int base;
  470. char *endptr;
  471. int matches;
  472. int lpref;
  473. matches = 0;
  474. while (1) {
  475. if (*format == '%') {
  476. /* start of pattern */
  477. lpref = 0;
  478. format++;
  479. if (*format == 'l') {
  480. /* same as in printf() */
  481. lpref = 1;
  482. format++;
  483. if (*format == 'l') {
  484. lpref = 2;
  485. format++;
  486. }
  487. }
  488. if (*format == '%') {
  489. /* literal % */
  490. if ('%' != *str)
  491. goto done;
  492. str++;
  493. format++;
  494. continue;
  495. } else if (*format == 'd') {
  496. ival = strtoll(str, &endptr, 10);
  497. if (lpref == 0)
  498. *va_arg(args, int *) = ival;
  499. else if (lpref == 1)
  500. *va_arg(args, long *) = ival;
  501. else if (lpref == 2)
  502. *va_arg(args, long long *) = ival;
  503. } else if (*format == 'u' || *format == 'x' || *format == 'X') {
  504. base = *format == 'u' ? 10 : 16;
  505. uval = strtoull(str, &endptr, base);
  506. if (lpref == 0)
  507. *va_arg(args, unsigned int *) = uval;
  508. else if (lpref == 1)
  509. *va_arg(args, unsigned long *) = uval;
  510. else if (lpref == 2)
  511. *va_arg(args, unsigned long long *) = uval;
  512. } else if (*format == 'p') {
  513. *va_arg(args, void **) = (void *)strtoul(str, &endptr, 16);
  514. } else {
  515. SET_ERRNO(EILSEQ);
  516. goto done;
  517. }
  518. format++;
  519. str = endptr;
  520. matches++;
  521. } else if (*format == '\0') {
  522. goto done;
  523. } else if (isspace(*format)) {
  524. /* skip spaces in format and str */
  525. while (isspace(*format))
  526. format++;
  527. while (isspace(*str))
  528. str++;
  529. } else if (*format == *str) {
  530. /* literal match */
  531. format++;
  532. str++;
  533. } else {
  534. if (!matches)
  535. matches = EOF;
  536. goto done;
  537. }
  538. }
  539. done:
  540. return matches;
  541. }
  542. static __attribute__((unused, format(scanf, 2, 3)))
  543. int sscanf(const char *str, const char *format, ...)
  544. {
  545. va_list args;
  546. int ret;
  547. va_start(args, format);
  548. ret = vsscanf(str, format, args);
  549. va_end(args);
  550. return ret;
  551. }
  552. static __attribute__((unused))
  553. void perror(const char *msg)
  554. {
  555. #ifdef NOLIBC_IGNORE_ERRNO
  556. fprintf(stderr, "%s%sunknown error\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "");
  557. #else
  558. fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno);
  559. #endif
  560. }
  561. static __attribute__((unused))
  562. int setvbuf(FILE *stream __attribute__((unused)),
  563. char *buf __attribute__((unused)),
  564. int mode,
  565. size_t size __attribute__((unused)))
  566. {
  567. /*
  568. * nolibc does not support buffering so this is a nop. Just check mode
  569. * is valid as required by the spec.
  570. */
  571. switch (mode) {
  572. case _IOFBF:
  573. case _IOLBF:
  574. case _IONBF:
  575. break;
  576. default:
  577. return EOF;
  578. }
  579. return 0;
  580. }
  581. static __attribute__((unused))
  582. const char *strerror(int errno)
  583. {
  584. static char buf[18] = "errno=";
  585. i64toa_r(errno, &buf[6]);
  586. return buf;
  587. }
  588. #endif /* _NOLIBC_STDIO_H */