summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-08-30 15:13:28 +0430
committerAndreas Kling <kling@serenityos.org>2020-08-31 09:14:11 +0200
commit9adbbff4dd5469a26a9d606e65ae9b7e5c32605a (patch)
treea4c91a054d2cc69a0ef52871dd37b201e0e55535
parentcb7526fca0aa6cb07d279fec93288d0169904bfc (diff)
downloadserenity-9adbbff4dd5469a26a9d606e65ae9b7e5c32605a.zip
LibC: Partially implement 'freopen'
-rw-r--r--Libraries/LibC/stdio.cpp36
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)