diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-08-30 15:13:28 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-31 09:14:11 +0200 |
commit | 9adbbff4dd5469a26a9d606e65ae9b7e5c32605a (patch) | |
tree | a4c91a054d2cc69a0ef52871dd37b201e0e55535 /Libraries/LibC | |
parent | cb7526fca0aa6cb07d279fec93288d0169904bfc (diff) | |
download | serenity-9adbbff4dd5469a26a9d606e65ae9b7e5c32605a.zip |
LibC: Partially implement 'freopen'
Diffstat (limited to 'Libraries/LibC')
-rw-r--r-- | Libraries/LibC/stdio.cpp | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/Libraries/LibC/stdio.cpp b/Libraries/LibC/stdio.cpp index 15d86dccc1..02f64d4165 100644 --- a/Libraries/LibC/stdio.cpp +++ b/Libraries/LibC/stdio.cpp @@ -77,6 +77,8 @@ public: pid_t popen_child() { return m_popen_child; } void set_popen_child(pid_t child_pid) { m_popen_child = child_pid; } + void reopen(int fd, int mode); + private: struct Buffer { // A ringbuffer that also transparently implements ungetc(). @@ -415,6 +417,23 @@ long FILE::tell() return lseek(m_fd, 0, SEEK_CUR); } +void FILE::reopen(int fd, int mode) +{ + // Dr. POSIX says: "Failure to flush or close the file descriptor + // successfully shall be ignored" + // and so we ignore any failures these two might have. + flush(); + close(); + + // Just in case flush() and close() didn't drop the buffer. + m_buffer.drop(); + + m_fd = fd; + m_mode = mode; + m_error = 0; + m_eof = false; +} + FILE::Buffer::~Buffer() { if (m_data_is_malloced) @@ -967,10 +986,19 @@ FILE* fopen(const char* pathname, const char* mode) FILE* freopen(const char* pathname, const char* mode, FILE* stream) { - (void)pathname; - (void)mode; - (void)stream; - ASSERT_NOT_REACHED(); + ASSERT(stream); + if (!pathname) { + // FIXME: Someone should probably implement this path. + TODO(); + } + + int flags = parse_mode(mode); + int fd = open(pathname, flags, 0666); + if (fd < 0) + return nullptr; + + stream->reopen(fd, flags); + return stream; } FILE* fdopen(int fd, const char* mode) |