stdio.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form must reproduce the above copyright notice,
  13. * this list of conditions and the following disclaimer in the documentation
  14. * and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  24. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <AK/LogStream.h>
  28. #include <AK/PrintfImplementation.h>
  29. #include <AK/ScopedValueRollback.h>
  30. #include <AK/StdLibExtras.h>
  31. #include <AK/kmalloc.h>
  32. #include <Kernel/API/Syscall.h>
  33. #include <assert.h>
  34. #include <errno.h>
  35. #include <fcntl.h>
  36. #include <stdarg.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <sys/types.h>
  41. #include <sys/wait.h>
  42. #include <unistd.h>
  43. struct FILE {
  44. public:
  45. FILE(int fd, int mode)
  46. : m_fd(fd)
  47. , m_mode(mode)
  48. {
  49. }
  50. ~FILE();
  51. static FILE* create(int fd, int mode);
  52. void setbuf(u8* data, int mode, size_t size) { m_buffer.setbuf(data, mode, size); }
  53. bool flush();
  54. bool close();
  55. int fileno() const { return m_fd; }
  56. bool eof() const { return m_eof; }
  57. int error() const { return m_error; }
  58. void clear_err() { m_error = 0; }
  59. size_t read(u8*, size_t);
  60. size_t write(const u8*, size_t);
  61. bool gets(u8*, size_t);
  62. bool ungetc(u8 byte) { return m_buffer.enqueue_front(byte); }
  63. int seek(long offset, int whence);
  64. long tell();
  65. pid_t popen_child() { return m_popen_child; }
  66. void set_popen_child(pid_t child_pid) { m_popen_child = child_pid; }
  67. private:
  68. struct Buffer {
  69. // A ringbuffer that also transparently implements ungetc().
  70. public:
  71. ~Buffer();
  72. int mode() const { return m_mode; }
  73. void setbuf(u8* data, int mode, size_t size);
  74. // Make sure to call realize() before enqueuing any data.
  75. // Dequeuing can be attempted without it.
  76. void realize(int fd);
  77. void drop();
  78. bool may_use() const { return m_ungotten || m_mode != _IONBF; }
  79. bool is_not_empty() const { return m_ungotten || !m_empty; }
  80. size_t buffered_size() const;
  81. const u8* begin_dequeue(size_t& available_size) const;
  82. void did_dequeue(size_t actual_size);
  83. u8* begin_enqueue(size_t& available_size) const;
  84. void did_enqueue(size_t actual_size);
  85. bool enqueue_front(u8 byte);
  86. private:
  87. // Note: the fields here are arranged this way
  88. // to make sizeof(Buffer) smaller.
  89. u8* m_data { nullptr };
  90. size_t m_capacity { BUFSIZ };
  91. size_t m_begin { 0 };
  92. size_t m_end { 0 };
  93. int m_mode { -1 };
  94. u8 m_unget_buffer { 0 };
  95. bool m_ungotten : 1 { false };
  96. bool m_data_is_malloced : 1 { false };
  97. // When m_begin == m_end, we want to distinguish whether
  98. // the buffer is full or empty.
  99. bool m_empty : 1 { true };
  100. };
  101. // Read or write using the underlying fd, bypassing the buffer.
  102. ssize_t do_read(u8*, size_t);
  103. ssize_t do_write(const u8*, size_t);
  104. // Read some data into the buffer.
  105. bool read_into_buffer();
  106. // Flush *some* data from the buffer.
  107. bool write_from_buffer();
  108. int m_fd { -1 };
  109. int m_mode { 0 };
  110. int m_error { 0 };
  111. bool m_eof { false };
  112. pid_t m_popen_child { -1 };
  113. Buffer m_buffer;
  114. };
  115. FILE::~FILE()
  116. {
  117. bool already_closed = m_fd == -1;
  118. ASSERT(already_closed);
  119. }
  120. FILE* FILE::create(int fd, int mode)
  121. {
  122. void* file = calloc(1, sizeof(FILE));
  123. new (file) FILE(fd, mode);
  124. return (FILE*)file;
  125. }
  126. bool FILE::close()
  127. {
  128. bool flush_ok = flush();
  129. int rc = ::close(m_fd);
  130. m_fd = -1;
  131. if (!flush_ok) {
  132. // Restore the original error from flush().
  133. errno = m_error;
  134. }
  135. return flush_ok && rc == 0;
  136. }
  137. bool FILE::flush()
  138. {
  139. if (m_mode & O_WRONLY && m_buffer.may_use()) {
  140. // When open for writing, write out all the buffered data.
  141. while (m_buffer.is_not_empty()) {
  142. bool ok = write_from_buffer();
  143. if (!ok)
  144. return false;
  145. }
  146. }
  147. if (m_mode & O_RDONLY) {
  148. // When open for reading, just drop the buffered data.
  149. size_t had_buffered = m_buffer.buffered_size();
  150. m_buffer.drop();
  151. // Attempt to reset the underlying file position to what the user
  152. // expects.
  153. int rc = lseek(m_fd, -had_buffered, SEEK_CUR);
  154. if (rc < 0) {
  155. if (errno == ESPIPE) {
  156. // We can't set offset on this file; oh well, the user will just
  157. // have to cope.
  158. errno = 0;
  159. } else {
  160. return false;
  161. }
  162. }
  163. }
  164. return true;
  165. }
  166. ssize_t FILE::do_read(u8* data, size_t size)
  167. {
  168. int nread = ::read(m_fd, data, size);
  169. if (nread < 0) {
  170. m_error = errno;
  171. } else if (nread == 0) {
  172. m_eof = true;
  173. }
  174. return nread;
  175. }
  176. ssize_t FILE::do_write(const u8* data, size_t size)
  177. {
  178. int nwritten = ::write(m_fd, data, size);
  179. if (nwritten < 0)
  180. m_error = errno;
  181. return nwritten;
  182. }
  183. bool FILE::read_into_buffer()
  184. {
  185. m_buffer.realize(m_fd);
  186. size_t available_size;
  187. u8* data = m_buffer.begin_enqueue(available_size);
  188. // If we want to read, the buffer must have some space!
  189. ASSERT(available_size);
  190. ssize_t nread = do_read(data, available_size);
  191. if (nread <= 0)
  192. return false;
  193. m_buffer.did_enqueue(nread);
  194. return true;
  195. }
  196. bool FILE::write_from_buffer()
  197. {
  198. size_t size;
  199. const u8* data = m_buffer.begin_dequeue(size);
  200. // If we want to write, the buffer must have something in it!
  201. ASSERT(size);
  202. ssize_t nwritten = do_write(data, size);
  203. if (nwritten < 0)
  204. return false;
  205. m_buffer.did_dequeue(nwritten);
  206. return true;
  207. }
  208. size_t FILE::read(u8* data, size_t size)
  209. {
  210. size_t total_read = 0;
  211. while (size > 0) {
  212. size_t actual_size;
  213. if (m_buffer.may_use()) {
  214. // Let's see if the buffer has something queued for us.
  215. size_t queued_size;
  216. const u8* queued_data = m_buffer.begin_dequeue(queued_size);
  217. if (queued_size == 0) {
  218. // Nothing buffered; we're going to have to read some.
  219. bool read_some_more = read_into_buffer();
  220. if (read_some_more) {
  221. // Great, now try this again.
  222. continue;
  223. }
  224. return total_read;
  225. }
  226. actual_size = min(size, queued_size);
  227. memcpy(data, queued_data, actual_size);
  228. m_buffer.did_dequeue(actual_size);
  229. } else {
  230. // Read directly into the user buffer.
  231. ssize_t nread = do_read(data, size);
  232. if (nread <= 0)
  233. return total_read;
  234. actual_size = nread;
  235. }
  236. total_read += actual_size;
  237. data += actual_size;
  238. size -= actual_size;
  239. }
  240. return total_read;
  241. }
  242. size_t FILE::write(const u8* data, size_t size)
  243. {
  244. size_t total_written = 0;
  245. while (size > 0) {
  246. size_t actual_size;
  247. if (m_buffer.may_use()) {
  248. m_buffer.realize(m_fd);
  249. // Try writing into the buffer.
  250. size_t available_size;
  251. u8* buffer_data = m_buffer.begin_enqueue(available_size);
  252. if (available_size == 0) {
  253. // There's no space in the buffer; we're going to free some.
  254. bool freed_some_space = write_from_buffer();
  255. if (freed_some_space) {
  256. // Great, now try this again.
  257. continue;
  258. }
  259. return total_written;
  260. }
  261. actual_size = min(size, available_size);
  262. memcpy(buffer_data, data, actual_size);
  263. m_buffer.did_enqueue(actual_size);
  264. // See if we have to flush it.
  265. if (m_buffer.mode() == _IOLBF) {
  266. bool includes_newline = memchr(data, '\n', actual_size);
  267. if (includes_newline)
  268. flush();
  269. }
  270. } else {
  271. // Write directly from the user buffer.
  272. ssize_t nwritten = do_write(data, size);
  273. if (nwritten < 0)
  274. return total_written;
  275. actual_size = nwritten;
  276. }
  277. total_written += actual_size;
  278. data += actual_size;
  279. size -= actual_size;
  280. }
  281. return total_written;
  282. }
  283. bool FILE::gets(u8* data, size_t size)
  284. {
  285. // gets() is a lot like read(), but it is different enough in how it
  286. // processes newlines and null-terminates the buffer that it deserves a
  287. // separate implementation.
  288. size_t total_read = 0;
  289. if (size == 0)
  290. return false;
  291. while (size > 1) {
  292. if (m_buffer.may_use()) {
  293. // Let's see if the buffer has something queued for us.
  294. size_t queued_size;
  295. const u8* queued_data = m_buffer.begin_dequeue(queued_size);
  296. if (queued_size == 0) {
  297. // Nothing buffered; we're going to have to read some.
  298. bool read_some_more = read_into_buffer();
  299. if (read_some_more) {
  300. // Great, now try this again.
  301. continue;
  302. }
  303. *data = 0;
  304. return total_read > 0;
  305. }
  306. size_t actual_size = min(size - 1, queued_size);
  307. u8* newline = reinterpret_cast<u8*>(memchr(queued_data, '\n', actual_size));
  308. if (newline)
  309. actual_size = newline - queued_data + 1;
  310. memcpy(data, queued_data, actual_size);
  311. m_buffer.did_dequeue(actual_size);
  312. total_read += actual_size;
  313. data += actual_size;
  314. size -= actual_size;
  315. if (newline)
  316. break;
  317. } else {
  318. // Sadly, we have to actually read these characters one by one.
  319. u8 byte;
  320. ssize_t nread = do_read(&byte, 1);
  321. if (nread <= 0) {
  322. *data = 0;
  323. return total_read > 0;
  324. }
  325. ASSERT(nread == 1);
  326. *data = byte;
  327. total_read++;
  328. data++;
  329. size--;
  330. if (byte == '\n')
  331. break;
  332. }
  333. }
  334. *data = 0;
  335. return total_read > 0;
  336. }
  337. int FILE::seek(long offset, int whence)
  338. {
  339. bool ok = flush();
  340. if (!ok)
  341. return -1;
  342. off_t off = lseek(m_fd, offset, whence);
  343. if (off < 0) {
  344. // Note: do not set m_error.
  345. return off;
  346. }
  347. m_eof = false;
  348. return 0;
  349. }
  350. long FILE::tell()
  351. {
  352. bool ok = flush();
  353. if (!ok)
  354. return -1;
  355. return lseek(m_fd, 0, SEEK_CUR);
  356. }
  357. FILE::Buffer::~Buffer()
  358. {
  359. if (m_data_is_malloced)
  360. free(m_data);
  361. }
  362. void FILE::Buffer::realize(int fd)
  363. {
  364. if (m_mode == -1)
  365. m_mode = isatty(fd) ? _IOLBF : _IOFBF;
  366. if (m_mode != _IONBF && m_data == nullptr) {
  367. m_data = reinterpret_cast<u8*>(malloc(m_capacity));
  368. m_data_is_malloced = true;
  369. }
  370. }
  371. void FILE::Buffer::setbuf(u8* data, int mode, size_t size)
  372. {
  373. drop();
  374. m_mode = mode;
  375. if (data != nullptr) {
  376. m_data = data;
  377. m_capacity = size;
  378. }
  379. }
  380. void FILE::Buffer::drop()
  381. {
  382. if (m_data_is_malloced) {
  383. free(m_data);
  384. m_data = nullptr;
  385. m_data_is_malloced = false;
  386. }
  387. m_begin = m_end = 0;
  388. m_empty = true;
  389. m_ungotten = false;
  390. }
  391. size_t FILE::Buffer::buffered_size() const
  392. {
  393. // Note: does not include the ungetc() buffer.
  394. if (m_empty)
  395. return 0;
  396. if (m_begin < m_end)
  397. return m_end - m_begin;
  398. else
  399. return m_capacity - (m_begin - m_end);
  400. }
  401. const u8* FILE::Buffer::begin_dequeue(size_t& available_size) const
  402. {
  403. if (m_ungotten) {
  404. available_size = 1;
  405. return &m_unget_buffer;
  406. }
  407. if (m_empty) {
  408. available_size = 0;
  409. return nullptr;
  410. }
  411. if (m_begin < m_end)
  412. available_size = m_end - m_begin;
  413. else
  414. available_size = m_capacity - m_begin;
  415. return &m_data[m_begin];
  416. }
  417. void FILE::Buffer::did_dequeue(size_t actual_size)
  418. {
  419. ASSERT(actual_size > 0);
  420. if (m_ungotten) {
  421. ASSERT(actual_size == 1);
  422. m_ungotten = false;
  423. return;
  424. }
  425. m_begin += actual_size;
  426. ASSERT(m_begin <= m_capacity);
  427. if (m_begin == m_capacity) {
  428. // Wrap around.
  429. m_begin = 0;
  430. }
  431. if (m_begin == m_end) {
  432. m_empty = true;
  433. // As an optimization, move both pointers to the beginning of the
  434. // buffer, so that more consecutive space is available next time.
  435. m_begin = m_end = 0;
  436. }
  437. }
  438. u8* FILE::Buffer::begin_enqueue(size_t& available_size) const
  439. {
  440. ASSERT(m_data != nullptr);
  441. if (m_begin < m_end || m_empty)
  442. available_size = m_capacity - m_end;
  443. else
  444. available_size = m_begin - m_end;
  445. return const_cast<u8*>(&m_data[m_end]);
  446. }
  447. void FILE::Buffer::did_enqueue(size_t actual_size)
  448. {
  449. ASSERT(m_data != nullptr);
  450. ASSERT(actual_size > 0);
  451. m_end += actual_size;
  452. ASSERT(m_end <= m_capacity);
  453. if (m_end == m_capacity) {
  454. // Wrap around.
  455. m_end = 0;
  456. }
  457. m_empty = false;
  458. }
  459. bool FILE::Buffer::enqueue_front(u8 byte)
  460. {
  461. if (m_ungotten) {
  462. // Sorry, the place is already taken!
  463. return false;
  464. }
  465. m_ungotten = true;
  466. m_unget_buffer = byte;
  467. return true;
  468. }
  469. extern "C" {
  470. static u8 default_streams[3][sizeof(FILE)];
  471. FILE* stdin = reinterpret_cast<FILE*>(&default_streams[0]);
  472. FILE* stdout = reinterpret_cast<FILE*>(&default_streams[1]);
  473. FILE* stderr = reinterpret_cast<FILE*>(&default_streams[2]);
  474. void __stdio_init()
  475. {
  476. new (stdin) FILE(0, O_RDONLY);
  477. new (stdout) FILE(1, O_WRONLY);
  478. new (stderr) FILE(2, O_WRONLY);
  479. stderr->setbuf(nullptr, _IONBF, 0);
  480. }
  481. int setvbuf(FILE* stream, char* buf, int mode, size_t size)
  482. {
  483. ASSERT(stream);
  484. if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF) {
  485. errno = EINVAL;
  486. return -1;
  487. }
  488. stream->setbuf(reinterpret_cast<u8*>(buf), mode, size);
  489. return 0;
  490. }
  491. void setbuf(FILE* stream, char* buf)
  492. {
  493. setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
  494. }
  495. void setlinebuf(FILE* stream)
  496. {
  497. setvbuf(stream, nullptr, _IOLBF, 0);
  498. }
  499. int fileno(FILE* stream)
  500. {
  501. ASSERT(stream);
  502. return stream->fileno();
  503. }
  504. int feof(FILE* stream)
  505. {
  506. ASSERT(stream);
  507. return stream->eof();
  508. }
  509. int fflush(FILE* stream)
  510. {
  511. if (!stream) {
  512. dbg() << "FIXME: fflush(nullptr) should flush all open streams";
  513. return 0;
  514. }
  515. return stream->flush() ? 0 : EOF;
  516. }
  517. char* fgets(char* buffer, int size, FILE* stream)
  518. {
  519. ASSERT(stream);
  520. bool ok = stream->gets(reinterpret_cast<u8*>(buffer), size);
  521. return ok ? buffer : nullptr;
  522. }
  523. int fgetc(FILE* stream)
  524. {
  525. ASSERT(stream);
  526. char ch;
  527. size_t nread = fread(&ch, sizeof(char), 1, stream);
  528. if (nread == 1)
  529. return ch;
  530. return EOF;
  531. }
  532. int getc(FILE* stream)
  533. {
  534. return fgetc(stream);
  535. }
  536. int getc_unlocked(FILE* stream)
  537. {
  538. return fgetc(stream);
  539. }
  540. int getchar()
  541. {
  542. return getc(stdin);
  543. }
  544. ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* stream)
  545. {
  546. char *ptr, *eptr;
  547. if (*lineptr == nullptr || *n == 0) {
  548. *n = BUFSIZ;
  549. if ((*lineptr = static_cast<char*>(malloc(*n))) == nullptr) {
  550. return -1;
  551. }
  552. }
  553. for (ptr = *lineptr, eptr = *lineptr + *n;;) {
  554. int c = fgetc(stream);
  555. if (c == -1) {
  556. if (feof(stream)) {
  557. *ptr = '\0';
  558. return ptr == *lineptr ? -1 : ptr - *lineptr;
  559. } else {
  560. return -1;
  561. }
  562. }
  563. *ptr++ = c;
  564. if (c == delim) {
  565. *ptr = '\0';
  566. return ptr - *lineptr;
  567. }
  568. if (ptr + 2 >= eptr) {
  569. char* nbuf;
  570. size_t nbuf_sz = *n * 2;
  571. ssize_t d = ptr - *lineptr;
  572. if ((nbuf = static_cast<char*>(realloc(*lineptr, nbuf_sz))) == nullptr) {
  573. return -1;
  574. }
  575. *lineptr = nbuf;
  576. *n = nbuf_sz;
  577. eptr = nbuf + nbuf_sz;
  578. ptr = nbuf + d;
  579. }
  580. }
  581. }
  582. ssize_t getline(char** lineptr, size_t* n, FILE* stream)
  583. {
  584. return getdelim(lineptr, n, '\n', stream);
  585. }
  586. int ungetc(int c, FILE* stream)
  587. {
  588. ASSERT(stream);
  589. bool ok = stream->ungetc(c);
  590. return ok ? c : EOF;
  591. }
  592. int fputc(int ch, FILE* stream)
  593. {
  594. ASSERT(stream);
  595. u8 byte = ch;
  596. size_t nwritten = stream->write(&byte, 1);
  597. if (nwritten == 0)
  598. return EOF;
  599. ASSERT(nwritten == 1);
  600. return byte;
  601. }
  602. int putc(int ch, FILE* stream)
  603. {
  604. return fputc(ch, stream);
  605. }
  606. int putchar(int ch)
  607. {
  608. return putc(ch, stdout);
  609. }
  610. int fputs(const char* s, FILE* stream)
  611. {
  612. ASSERT(stream);
  613. size_t len = strlen(s);
  614. size_t nwritten = stream->write(reinterpret_cast<const u8*>(s), len);
  615. if (nwritten < len)
  616. return EOF;
  617. return 1;
  618. }
  619. int puts(const char* s)
  620. {
  621. int rc = fputs(s, stdout);
  622. if (rc == EOF)
  623. return EOF;
  624. return fputc('\n', stdout);
  625. }
  626. void clearerr(FILE* stream)
  627. {
  628. ASSERT(stream);
  629. stream->clear_err();
  630. }
  631. int ferror(FILE* stream)
  632. {
  633. ASSERT(stream);
  634. return stream->error();
  635. }
  636. size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
  637. {
  638. ASSERT(stream);
  639. ASSERT(!Checked<size_t>::multiplication_would_overflow(size, nmemb));
  640. size_t nread = stream->read(reinterpret_cast<u8*>(ptr), size * nmemb);
  641. return nread / size;
  642. }
  643. size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream)
  644. {
  645. ASSERT(stream);
  646. ASSERT(!Checked<size_t>::multiplication_would_overflow(size, nmemb));
  647. size_t nwritten = stream->write(reinterpret_cast<const u8*>(ptr), size * nmemb);
  648. return nwritten / size;
  649. }
  650. int fseek(FILE* stream, long offset, int whence)
  651. {
  652. ASSERT(stream);
  653. return stream->seek(offset, whence);
  654. }
  655. long ftell(FILE* stream)
  656. {
  657. ASSERT(stream);
  658. return stream->tell();
  659. }
  660. int fgetpos(FILE* stream, fpos_t* pos)
  661. {
  662. ASSERT(stream);
  663. ASSERT(pos);
  664. long val = stream->tell();
  665. if (val == -1L)
  666. return 1;
  667. *pos = val;
  668. return 0;
  669. }
  670. int fsetpos(FILE* stream, const fpos_t* pos)
  671. {
  672. ASSERT(stream);
  673. ASSERT(pos);
  674. return stream->seek((long)*pos, SEEK_SET);
  675. }
  676. void rewind(FILE* stream)
  677. {
  678. ASSERT(stream);
  679. int rc = stream->seek(0, SEEK_SET);
  680. ASSERT(rc == 0);
  681. }
  682. int vdbgprintf(const char* fmt, va_list ap)
  683. {
  684. return printf_internal([](char*&, char ch) { dbgputch(ch); }, nullptr, fmt, ap);
  685. }
  686. int dbgprintf(const char* fmt, ...)
  687. {
  688. va_list ap;
  689. va_start(ap, fmt);
  690. int ret = printf_internal([](char*&, char ch) { dbgputch(ch); }, nullptr, fmt, ap);
  691. va_end(ap);
  692. return ret;
  693. }
  694. ALWAYS_INLINE void stdout_putch(char*&, char ch)
  695. {
  696. putchar(ch);
  697. }
  698. static FILE* __current_stream = nullptr;
  699. ALWAYS_INLINE static void stream_putch(char*&, char ch)
  700. {
  701. fputc(ch, __current_stream);
  702. }
  703. int vfprintf(FILE* stream, const char* fmt, va_list ap)
  704. {
  705. __current_stream = stream;
  706. return printf_internal(stream_putch, nullptr, fmt, ap);
  707. }
  708. int fprintf(FILE* stream, const char* fmt, ...)
  709. {
  710. va_list ap;
  711. va_start(ap, fmt);
  712. int ret = vfprintf(stream, fmt, ap);
  713. va_end(ap);
  714. return ret;
  715. }
  716. int vprintf(const char* fmt, va_list ap)
  717. {
  718. return printf_internal(stdout_putch, nullptr, fmt, ap);
  719. }
  720. int printf(const char* fmt, ...)
  721. {
  722. va_list ap;
  723. va_start(ap, fmt);
  724. int ret = vprintf(fmt, ap);
  725. va_end(ap);
  726. return ret;
  727. }
  728. static void buffer_putch(char*& bufptr, char ch)
  729. {
  730. *bufptr++ = ch;
  731. }
  732. int vsprintf(char* buffer, const char* fmt, va_list ap)
  733. {
  734. int ret = printf_internal(buffer_putch, buffer, fmt, ap);
  735. buffer[ret] = '\0';
  736. return ret;
  737. }
  738. int sprintf(char* buffer, const char* fmt, ...)
  739. {
  740. va_list ap;
  741. va_start(ap, fmt);
  742. int ret = vsprintf(buffer, fmt, ap);
  743. va_end(ap);
  744. return ret;
  745. }
  746. static size_t __vsnprintf_space_remaining;
  747. ALWAYS_INLINE void sized_buffer_putch(char*& bufptr, char ch)
  748. {
  749. if (__vsnprintf_space_remaining) {
  750. *bufptr++ = ch;
  751. --__vsnprintf_space_remaining;
  752. }
  753. }
  754. int vsnprintf(char* buffer, size_t size, const char* fmt, va_list ap)
  755. {
  756. __vsnprintf_space_remaining = size;
  757. int ret = printf_internal(sized_buffer_putch, buffer, fmt, ap);
  758. if (__vsnprintf_space_remaining) {
  759. buffer[ret] = '\0';
  760. }
  761. return ret;
  762. }
  763. int snprintf(char* buffer, size_t size, const char* fmt, ...)
  764. {
  765. va_list ap;
  766. va_start(ap, fmt);
  767. int ret = vsnprintf(buffer, size, fmt, ap);
  768. va_end(ap);
  769. return ret;
  770. }
  771. void perror(const char* s)
  772. {
  773. int saved_errno = errno;
  774. dbg() << "perror(): " << s << ": " << strerror(saved_errno);
  775. fprintf(stderr, "%s: %s\n", s, strerror(saved_errno));
  776. }
  777. static int parse_mode(const char* mode)
  778. {
  779. int flags = 0;
  780. // NOTE: rt is a non-standard mode which opens a file for read, explicitly
  781. // specifying that it's a text file
  782. for (auto* ptr = mode; *ptr; ++ptr) {
  783. switch (*ptr) {
  784. case 'r':
  785. flags |= O_RDONLY;
  786. break;
  787. case 'w':
  788. flags |= O_WRONLY | O_CREAT | O_TRUNC;
  789. break;
  790. case 'a':
  791. flags |= O_WRONLY | O_APPEND | O_CREAT;
  792. break;
  793. case '+':
  794. flags |= O_RDWR;
  795. break;
  796. case 'e':
  797. flags |= O_CLOEXEC;
  798. break;
  799. case 'b':
  800. // Ok...
  801. break;
  802. case 't':
  803. // Ok...
  804. break;
  805. default:
  806. dbg() << "Potentially unsupported fopen mode _" << mode << "_ (because of '" << *ptr << "')";
  807. }
  808. }
  809. return flags;
  810. }
  811. FILE* fopen(const char* pathname, const char* mode)
  812. {
  813. int flags = parse_mode(mode);
  814. int fd = open(pathname, flags, 0666);
  815. if (fd < 0)
  816. return nullptr;
  817. return FILE::create(fd, flags);
  818. }
  819. FILE* freopen(const char* pathname, const char* mode, FILE* stream)
  820. {
  821. (void)pathname;
  822. (void)mode;
  823. (void)stream;
  824. ASSERT_NOT_REACHED();
  825. }
  826. FILE* fdopen(int fd, const char* mode)
  827. {
  828. int flags = parse_mode(mode);
  829. // FIXME: Verify that the mode matches how fd is already open.
  830. if (fd < 0)
  831. return nullptr;
  832. return FILE::create(fd, flags);
  833. }
  834. static inline bool is_default_stream(FILE* stream)
  835. {
  836. return stream == stdin || stream == stdout || stream == stderr;
  837. }
  838. int fclose(FILE* stream)
  839. {
  840. ASSERT(stream);
  841. bool ok = stream->close();
  842. ScopedValueRollback errno_restorer(errno);
  843. stream->~FILE();
  844. if (!is_default_stream(stream))
  845. free(stream);
  846. return ok ? 0 : EOF;
  847. }
  848. int rename(const char* oldpath, const char* newpath)
  849. {
  850. if (!oldpath || !newpath) {
  851. errno = EFAULT;
  852. return -1;
  853. }
  854. Syscall::SC_rename_params params { { oldpath, strlen(oldpath) }, { newpath, strlen(newpath) } };
  855. int rc = syscall(SC_rename, &params);
  856. __RETURN_WITH_ERRNO(rc, rc, -1);
  857. }
  858. void dbgputch(char ch)
  859. {
  860. syscall(SC_dbgputch, ch);
  861. }
  862. ssize_t dbgputstr(const char* characters, ssize_t length)
  863. {
  864. int rc = syscall(SC_dbgputstr, characters, length);
  865. __RETURN_WITH_ERRNO(rc, rc, -1);
  866. }
  867. char* tmpnam(char*)
  868. {
  869. ASSERT_NOT_REACHED();
  870. }
  871. FILE* popen(const char* command, const char* type)
  872. {
  873. if (!type || (*type != 'r' && *type != 'w')) {
  874. errno = EINVAL;
  875. return nullptr;
  876. }
  877. int pipe_fds[2];
  878. int rc = pipe(pipe_fds);
  879. if (rc < 0) {
  880. ScopedValueRollback rollback(errno);
  881. perror("pipe");
  882. return nullptr;
  883. }
  884. pid_t child_pid = fork();
  885. if (child_pid < 0) {
  886. ScopedValueRollback rollback(errno);
  887. perror("fork");
  888. close(pipe_fds[0]);
  889. close(pipe_fds[1]);
  890. return nullptr;
  891. } else if (child_pid == 0) {
  892. if (*type == 'r') {
  893. int rc = dup2(pipe_fds[1], STDOUT_FILENO);
  894. if (rc < 0) {
  895. perror("dup2");
  896. exit(1);
  897. }
  898. close(pipe_fds[0]);
  899. close(pipe_fds[1]);
  900. } else if (*type == 'w') {
  901. int rc = dup2(pipe_fds[0], STDIN_FILENO);
  902. if (rc < 0) {
  903. perror("dup2");
  904. exit(1);
  905. }
  906. close(pipe_fds[0]);
  907. close(pipe_fds[1]);
  908. }
  909. int rc = execl("/bin/sh", "sh", "-c", command, nullptr);
  910. if (rc < 0)
  911. perror("execl");
  912. exit(1);
  913. }
  914. FILE* file = nullptr;
  915. if (*type == 'r') {
  916. file = FILE::create(pipe_fds[0], O_RDONLY);
  917. close(pipe_fds[1]);
  918. } else if (*type == 'w') {
  919. file = FILE::create(pipe_fds[1], O_WRONLY);
  920. close(pipe_fds[0]);
  921. }
  922. file->set_popen_child(child_pid);
  923. return file;
  924. }
  925. int pclose(FILE* stream)
  926. {
  927. ASSERT(stream);
  928. ASSERT(stream->popen_child() != 0);
  929. int wstatus = 0;
  930. int rc = waitpid(stream->popen_child(), &wstatus, 0);
  931. if (rc < 0)
  932. return rc;
  933. return wstatus;
  934. }
  935. int remove(const char* pathname)
  936. {
  937. int rc = unlink(pathname);
  938. if (rc < 0 && errno != EISDIR)
  939. return -1;
  940. return rmdir(pathname);
  941. }
  942. int scanf(const char* fmt, ...)
  943. {
  944. va_list ap;
  945. va_start(ap, fmt);
  946. int count = vfscanf(stdin, fmt, ap);
  947. va_end(ap);
  948. return count;
  949. }
  950. int fscanf(FILE* stream, const char* fmt, ...)
  951. {
  952. va_list ap;
  953. va_start(ap, fmt);
  954. int count = vfscanf(stream, fmt, ap);
  955. va_end(ap);
  956. return count;
  957. }
  958. int sscanf(const char* buffer, const char* fmt, ...)
  959. {
  960. va_list ap;
  961. va_start(ap, fmt);
  962. int count = vsscanf(buffer, fmt, ap);
  963. va_end(ap);
  964. return count;
  965. }
  966. int vfscanf(FILE* stream, const char* fmt, va_list ap)
  967. {
  968. char buffer[BUFSIZ];
  969. if (!fgets(buffer, sizeof(buffer) - 1, stream))
  970. return -1;
  971. return vsscanf(buffer, fmt, ap);
  972. }
  973. void flockfile(FILE* filehandle)
  974. {
  975. (void)filehandle;
  976. dbgprintf("FIXME: Implement flockfile()\n");
  977. }
  978. void funlockfile(FILE* filehandle)
  979. {
  980. (void)filehandle;
  981. dbgprintf("FIXME: Implement funlockfile()\n");
  982. }
  983. FILE* tmpfile()
  984. {
  985. char tmp_path[] = "/tmp/XXXXXX";
  986. if (__generate_unique_filename(tmp_path) < 0)
  987. return nullptr;
  988. int fd = open(tmp_path, O_CREAT | O_EXCL | O_RDWR, S_IWUSR | S_IRUSR);
  989. if (fd < 0)
  990. return nullptr;
  991. // FIXME: instead of using this hack, implement with O_TMPFILE or similar
  992. unlink(tmp_path);
  993. return fdopen(fd, "rw");
  994. }
  995. }