stdio.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/LogStream.h>
  27. #include <AK/PrintfImplementation.h>
  28. #include <AK/ScopedValueRollback.h>
  29. #include <AK/StdLibExtras.h>
  30. #include <Kernel/Syscall.h>
  31. #include <assert.h>
  32. #include <errno.h>
  33. #include <fcntl.h>
  34. #include <stdarg.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <sys/types.h>
  39. #include <unistd.h>
  40. extern "C" {
  41. static FILE __default_streams[3];
  42. FILE* stdin;
  43. FILE* stdout;
  44. FILE* stderr;
  45. void init_FILE(FILE& fp, int fd, int mode)
  46. {
  47. fp.fd = fd;
  48. fp.buffer = fp.default_buffer;
  49. fp.buffer_size = BUFSIZ;
  50. fp.mode = mode;
  51. }
  52. static FILE* make_FILE(int fd)
  53. {
  54. auto* fp = (FILE*)malloc(sizeof(FILE));
  55. memset(fp, 0, sizeof(FILE));
  56. init_FILE(*fp, fd, isatty(fd));
  57. return fp;
  58. }
  59. void __stdio_init()
  60. {
  61. stdin = &__default_streams[0];
  62. stdout = &__default_streams[1];
  63. stderr = &__default_streams[2];
  64. init_FILE(*stdin, 0, isatty(0) ? _IOLBF : _IOFBF);
  65. init_FILE(*stdout, 1, isatty(1) ? _IOLBF : _IOFBF);
  66. init_FILE(*stderr, 2, _IONBF);
  67. }
  68. int setvbuf(FILE* stream, char* buf, int mode, size_t size)
  69. {
  70. if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF) {
  71. errno = EINVAL;
  72. return -1;
  73. }
  74. stream->mode = mode;
  75. if (buf) {
  76. stream->buffer = buf;
  77. stream->buffer_size = size;
  78. } else {
  79. stream->buffer = stream->default_buffer;
  80. stream->buffer_size = BUFSIZ;
  81. }
  82. stream->buffer_index = 0;
  83. return 0;
  84. }
  85. void setbuf(FILE* stream, char* buf)
  86. {
  87. setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
  88. }
  89. void setlinebuf(FILE* stream)
  90. {
  91. setvbuf(stream, nullptr, _IOLBF, 0);
  92. }
  93. int fileno(FILE* stream)
  94. {
  95. assert(stream);
  96. return stream->fd;
  97. }
  98. int feof(FILE* stream)
  99. {
  100. assert(stream);
  101. return stream->eof;
  102. }
  103. int fflush(FILE* stream)
  104. {
  105. // FIXME: fflush(NULL) should flush all open output streams.
  106. ASSERT(stream);
  107. if (!stream->buffer_index)
  108. return 0;
  109. int rc = write(stream->fd, stream->buffer, stream->buffer_index);
  110. stream->buffer_index = 0;
  111. stream->error = 0;
  112. stream->eof = 0;
  113. stream->have_ungotten = false;
  114. stream->ungotten = 0;
  115. if (rc < 0) {
  116. stream->error = errno;
  117. return EOF;
  118. }
  119. return 0;
  120. }
  121. char* fgets(char* buffer, int size, FILE* stream)
  122. {
  123. ASSERT(stream);
  124. ASSERT(size);
  125. ssize_t nread = 0;
  126. while (nread < (size - 1)) {
  127. int ch = fgetc(stream);
  128. if (ch == EOF)
  129. break;
  130. buffer[nread++] = ch;
  131. if (ch == '\n')
  132. break;
  133. }
  134. if (nread) {
  135. buffer[nread] = '\0';
  136. return buffer;
  137. }
  138. return nullptr;
  139. }
  140. int fgetc(FILE* stream)
  141. {
  142. assert(stream);
  143. char ch;
  144. size_t nread = fread(&ch, sizeof(char), 1, stream);
  145. if (nread == 1)
  146. return ch;
  147. return EOF;
  148. }
  149. int getc(FILE* stream)
  150. {
  151. return fgetc(stream);
  152. }
  153. int getc_unlocked(FILE* stream)
  154. {
  155. return fgetc(stream);
  156. }
  157. int getchar()
  158. {
  159. return getc(stdin);
  160. }
  161. ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* stream)
  162. {
  163. char *ptr, *eptr;
  164. if (*lineptr == nullptr || *n == 0) {
  165. *n = BUFSIZ;
  166. if ((*lineptr = static_cast<char*>(malloc(*n))) == nullptr) {
  167. return -1;
  168. }
  169. }
  170. for (ptr = *lineptr, eptr = *lineptr + *n;;) {
  171. int c = fgetc(stream);
  172. if (c == -1) {
  173. if (feof(stream)) {
  174. return ptr == *lineptr ? -1 : ptr - *lineptr;
  175. } else {
  176. return -1;
  177. }
  178. }
  179. *ptr++ = c;
  180. if (c == delim) {
  181. *ptr = '\0';
  182. return ptr - *lineptr;
  183. }
  184. if (ptr + 2 >= eptr) {
  185. char* nbuf;
  186. size_t nbuf_sz = *n * 2;
  187. ssize_t d = ptr - *lineptr;
  188. if ((nbuf = static_cast<char*>(realloc(*lineptr, nbuf_sz))) == nullptr) {
  189. return -1;
  190. }
  191. *lineptr = nbuf;
  192. *n = nbuf_sz;
  193. eptr = nbuf + nbuf_sz;
  194. ptr = nbuf + d;
  195. }
  196. }
  197. }
  198. ssize_t getline(char** lineptr, size_t* n, FILE* stream)
  199. {
  200. return getdelim(lineptr, n, '\n', stream);
  201. }
  202. int ungetc(int c, FILE* stream)
  203. {
  204. ASSERT(stream);
  205. if (c == EOF)
  206. return EOF;
  207. if (stream->have_ungotten)
  208. return EOF;
  209. stream->have_ungotten = true;
  210. stream->ungotten = c;
  211. stream->eof = false;
  212. return c;
  213. }
  214. int fputc(int ch, FILE* stream)
  215. {
  216. assert(stream);
  217. assert(stream->buffer_index < stream->buffer_size);
  218. stream->buffer[stream->buffer_index++] = ch;
  219. if (stream->buffer_index >= stream->buffer_size)
  220. fflush(stream);
  221. else if (stream->mode == _IONBF || (stream->mode == _IOLBF && ch == '\n'))
  222. fflush(stream);
  223. if (stream->eof || stream->error)
  224. return EOF;
  225. return (u8)ch;
  226. }
  227. int putc(int ch, FILE* stream)
  228. {
  229. return fputc(ch, stream);
  230. }
  231. int putchar(int ch)
  232. {
  233. return putc(ch, stdout);
  234. }
  235. int fputs(const char* s, FILE* stream)
  236. {
  237. for (; *s; ++s) {
  238. int rc = putc(*s, stream);
  239. if (rc == EOF)
  240. return EOF;
  241. }
  242. return 1;
  243. }
  244. int puts(const char* s)
  245. {
  246. int rc = fputs(s, stdout);
  247. if (rc == EOF)
  248. return EOF;
  249. return fputc('\n', stdout);
  250. }
  251. void clearerr(FILE* stream)
  252. {
  253. assert(stream);
  254. stream->eof = false;
  255. stream->error = 0;
  256. }
  257. int ferror(FILE* stream)
  258. {
  259. return stream->error;
  260. }
  261. size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
  262. {
  263. assert(stream);
  264. if (!size)
  265. return 0;
  266. ssize_t nread = 0;
  267. if (stream->have_ungotten) {
  268. // FIXME: Support ungotten character even if size != 1.
  269. ASSERT(size == 1);
  270. ((char*)ptr)[0] = stream->ungotten;
  271. stream->have_ungotten = false;
  272. --nmemb;
  273. if (!nmemb)
  274. return 1;
  275. ptr = &((char*)ptr)[1];
  276. ++nread;
  277. }
  278. ssize_t rc = read(stream->fd, ptr, nmemb * size);
  279. if (rc < 0) {
  280. stream->error = errno;
  281. return 0;
  282. }
  283. if (rc == 0)
  284. stream->eof = true;
  285. nread += rc;
  286. return nread / size;
  287. }
  288. size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream)
  289. {
  290. assert(stream);
  291. auto* bytes = (const u8*)ptr;
  292. ssize_t nwritten = 0;
  293. for (size_t i = 0; i < (size * nmemb); ++i) {
  294. int rc = fputc(bytes[i], stream);
  295. if (rc == EOF)
  296. break;
  297. ++nwritten;
  298. }
  299. return nwritten / size;
  300. }
  301. int fseek(FILE* stream, long offset, int whence)
  302. {
  303. assert(stream);
  304. fflush(stream);
  305. off_t off = lseek(stream->fd, offset, whence);
  306. if (off < 0)
  307. return off;
  308. stream->eof = false;
  309. stream->error = 0;
  310. stream->have_ungotten = false;
  311. stream->ungotten = 0;
  312. return 0;
  313. }
  314. long ftell(FILE* stream)
  315. {
  316. assert(stream);
  317. fflush(stream);
  318. return lseek(stream->fd, 0, SEEK_CUR);
  319. }
  320. int fgetpos(FILE* stream, fpos_t* pos)
  321. {
  322. assert(stream);
  323. assert(pos);
  324. long val = ftell(stream);
  325. if (val == -1L)
  326. return 1;
  327. *pos = val;
  328. return 0;
  329. }
  330. int fsetpos(FILE* stream, const fpos_t* pos)
  331. {
  332. assert(stream);
  333. assert(pos);
  334. return fseek(stream, (long) *pos, SEEK_SET);
  335. }
  336. void rewind(FILE* stream)
  337. {
  338. ASSERT(stream);
  339. int rc = fseek(stream, 0, SEEK_SET);
  340. ASSERT(rc == 0);
  341. }
  342. int dbgprintf(const char* fmt, ...)
  343. {
  344. va_list ap;
  345. va_start(ap, fmt);
  346. int ret = printf_internal([](char*&, char ch) { dbgputch(ch); }, nullptr, fmt, ap);
  347. va_end(ap);
  348. return ret;
  349. }
  350. static void stdout_putch(char*&, char ch)
  351. {
  352. putchar(ch);
  353. }
  354. static FILE* __current_stream = nullptr;
  355. static void stream_putch(char*&, char ch)
  356. {
  357. fputc(ch, __current_stream);
  358. }
  359. int vfprintf(FILE* stream, const char* fmt, va_list ap)
  360. {
  361. __current_stream = stream;
  362. return printf_internal(stream_putch, nullptr, fmt, ap);
  363. }
  364. int fprintf(FILE* stream, const char* fmt, ...)
  365. {
  366. va_list ap;
  367. va_start(ap, fmt);
  368. int ret = vfprintf(stream, fmt, ap);
  369. va_end(ap);
  370. return ret;
  371. }
  372. int vprintf(const char* fmt, va_list ap)
  373. {
  374. return printf_internal(stdout_putch, nullptr, fmt, ap);
  375. }
  376. int printf(const char* fmt, ...)
  377. {
  378. va_list ap;
  379. va_start(ap, fmt);
  380. int ret = vprintf(fmt, ap);
  381. va_end(ap);
  382. return ret;
  383. }
  384. static void buffer_putch(char*& bufptr, char ch)
  385. {
  386. *bufptr++ = ch;
  387. }
  388. int vsprintf(char* buffer, const char* fmt, va_list ap)
  389. {
  390. int ret = printf_internal(buffer_putch, buffer, fmt, ap);
  391. buffer[ret] = '\0';
  392. return ret;
  393. }
  394. int sprintf(char* buffer, const char* fmt, ...)
  395. {
  396. va_list ap;
  397. va_start(ap, fmt);
  398. int ret = vsprintf(buffer, fmt, ap);
  399. va_end(ap);
  400. return ret;
  401. }
  402. static size_t __vsnprintf_space_remaining;
  403. static void sized_buffer_putch(char*& bufptr, char ch)
  404. {
  405. if (__vsnprintf_space_remaining) {
  406. *bufptr++ = ch;
  407. --__vsnprintf_space_remaining;
  408. }
  409. }
  410. int vsnprintf(char* buffer, size_t size, const char* fmt, va_list ap)
  411. {
  412. __vsnprintf_space_remaining = size;
  413. int ret = printf_internal(sized_buffer_putch, buffer, fmt, ap);
  414. if (__vsnprintf_space_remaining) {
  415. buffer[ret] = '\0';
  416. }
  417. return ret;
  418. }
  419. int snprintf(char* buffer, size_t size, const char* fmt, ...)
  420. {
  421. va_list ap;
  422. va_start(ap, fmt);
  423. int ret = vsnprintf(buffer, size, fmt, ap);
  424. va_end(ap);
  425. return ret;
  426. }
  427. void perror(const char* s)
  428. {
  429. int saved_errno = errno;
  430. dbg() << "perror(): " << s << ": " << strerror(saved_errno);
  431. fprintf(stderr, "%s: %s\n", s, strerror(saved_errno));
  432. }
  433. FILE* fopen(const char* pathname, const char* mode)
  434. {
  435. int flags = 0;
  436. // NOTE: rt is a non-standard mode which opens a file for read, explicitly
  437. // specifying that it's a text file
  438. if (!strcmp(mode, "r") || !strcmp(mode, "rb") || !strcmp(mode, "rt"))
  439. flags = O_RDONLY;
  440. else if (!strcmp(mode, "r+") || !strcmp(mode, "rb+"))
  441. flags = O_RDWR;
  442. else if (!strcmp(mode, "w") || !strcmp(mode, "wb"))
  443. flags = O_WRONLY | O_CREAT | O_TRUNC;
  444. else if (!strcmp(mode, "w+") || !strcmp(mode, "wb+"))
  445. flags = O_RDWR | O_CREAT | O_TRUNC;
  446. else if (!strcmp(mode, "a") || !strcmp(mode, "ab"))
  447. flags = O_WRONLY | O_APPEND | O_CREAT;
  448. else if (!strcmp(mode, "a+") || !strcmp(mode, "ab+"))
  449. flags = O_RDWR | O_APPEND | O_CREAT;
  450. else {
  451. fprintf(stderr, "FIXME(LibC): fopen('%s', '%s')\n", pathname, mode);
  452. ASSERT_NOT_REACHED();
  453. }
  454. int fd = open(pathname, flags, 0666);
  455. if (fd < 0)
  456. return nullptr;
  457. return make_FILE(fd);
  458. }
  459. FILE* freopen(const char* pathname, const char* mode, FILE* stream)
  460. {
  461. (void)pathname;
  462. (void)mode;
  463. (void)stream;
  464. ASSERT_NOT_REACHED();
  465. }
  466. FILE* fdopen(int fd, const char* mode)
  467. {
  468. UNUSED_PARAM(mode);
  469. // FIXME: Verify that the mode matches how fd is already open.
  470. if (fd < 0)
  471. return nullptr;
  472. return make_FILE(fd);
  473. }
  474. int fclose(FILE* stream)
  475. {
  476. fflush(stream);
  477. int rc = close(stream->fd);
  478. if (stream != &__default_streams[0] && stream != &__default_streams[1] && stream != &__default_streams[2])
  479. free(stream);
  480. return rc;
  481. }
  482. int rename(const char* oldpath, const char* newpath)
  483. {
  484. if (!oldpath || !newpath) {
  485. errno = EFAULT;
  486. return -1;
  487. }
  488. Syscall::SC_rename_params params { { oldpath, strlen(oldpath) }, { newpath, strlen(newpath) } };
  489. int rc = syscall(SC_rename, &params);
  490. __RETURN_WITH_ERRNO(rc, rc, -1);
  491. }
  492. void dbgputch(char ch)
  493. {
  494. syscall(SC_dbgputch, ch);
  495. }
  496. int dbgputstr(const char* characters, int length)
  497. {
  498. int rc = syscall(SC_dbgputstr, characters, length);
  499. __RETURN_WITH_ERRNO(rc, rc, -1);
  500. }
  501. char* tmpnam(char*)
  502. {
  503. ASSERT_NOT_REACHED();
  504. }
  505. FILE* popen(const char* command, const char* type)
  506. {
  507. if (!type || (*type != 'r' && *type != 'w')) {
  508. errno = EINVAL;
  509. return nullptr;
  510. }
  511. int pipe_fds[2];
  512. int rc = pipe(pipe_fds);
  513. if (rc < 0) {
  514. ScopedValueRollback rollback(errno);
  515. perror("pipe");
  516. return nullptr;
  517. }
  518. pid_t child_pid = fork();
  519. if (!child_pid) {
  520. if (*type == 'r') {
  521. int rc = dup2(pipe_fds[1], STDOUT_FILENO);
  522. if (rc < 0) {
  523. perror("dup2");
  524. exit(1);
  525. }
  526. close(pipe_fds[0]);
  527. close(pipe_fds[1]);
  528. } else if (*type == 'w') {
  529. int rc = dup2(pipe_fds[0], STDIN_FILENO);
  530. if (rc < 0) {
  531. perror("dup2");
  532. exit(1);
  533. }
  534. close(pipe_fds[0]);
  535. close(pipe_fds[1]);
  536. }
  537. int rc = execl("/bin/sh", "sh", "-c", command, nullptr);
  538. if (rc < 0)
  539. perror("execl");
  540. exit(1);
  541. }
  542. FILE* fp = nullptr;
  543. if (*type == 'r') {
  544. fp = make_FILE(pipe_fds[0]);
  545. close(pipe_fds[1]);
  546. } else if (*type == 'w') {
  547. fp = make_FILE(pipe_fds[1]);
  548. close(pipe_fds[0]);
  549. }
  550. fp->popen_child = child_pid;
  551. return fp;
  552. }
  553. int pclose(FILE* fp)
  554. {
  555. ASSERT(fp);
  556. ASSERT(fp->popen_child != 0);
  557. int wstatus = 0;
  558. int rc = waitpid(fp->popen_child, &wstatus, 0);
  559. if (rc < 0)
  560. return rc;
  561. return wstatus;
  562. }
  563. int remove(const char* pathname)
  564. {
  565. int rc = unlink(pathname);
  566. if (rc < 0 && errno != EISDIR)
  567. return -1;
  568. return rmdir(pathname);
  569. }
  570. int scanf(const char* fmt, ...)
  571. {
  572. va_list ap;
  573. va_start(ap, fmt);
  574. int count = vfscanf(stdin, fmt, ap);
  575. va_end(ap);
  576. return count;
  577. }
  578. int fscanf(FILE* stream, const char* fmt, ...)
  579. {
  580. va_list ap;
  581. va_start(ap, fmt);
  582. int count = vfscanf(stream, fmt, ap);
  583. va_end(ap);
  584. return count;
  585. }
  586. int sscanf(const char* buffer, const char* fmt, ...)
  587. {
  588. va_list ap;
  589. va_start(ap, fmt);
  590. int count = vsscanf(buffer, fmt, ap);
  591. va_end(ap);
  592. return count;
  593. }
  594. int vfscanf(FILE* stream, const char* fmt, va_list ap)
  595. {
  596. char buffer[BUFSIZ];
  597. if (!fgets(buffer, sizeof(buffer) - 1, stream))
  598. return -1;
  599. return vsscanf(buffer, fmt, ap);
  600. }
  601. void flockfile(FILE* filehandle)
  602. {
  603. (void)filehandle;
  604. dbgprintf("FIXME: Implement flockfile()\n");
  605. }
  606. void funlockfile(FILE* filehandle)
  607. {
  608. (void)filehandle;
  609. dbgprintf("FIXME: Implement funlockfile()\n");
  610. }
  611. FILE* tmpfile()
  612. {
  613. char tmp_path[] = "/tmp/XXXXXX";
  614. if (__generate_unique_filename(tmp_path) < 0)
  615. return nullptr;
  616. int fd = open(tmp_path, O_CREAT | O_EXCL | O_RDWR, S_IWUSR | S_IRUSR);
  617. if (fd < 0)
  618. return nullptr;
  619. // FIXME: instead of using this hack, implement with O_TMPFILE or similar
  620. unlink(tmp_path);
  621. return make_FILE(fd);
  622. }
  623. }