diff options
author | Tim Schumacher <timschumi@gmx.de> | 2021-05-26 08:39:19 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-05-30 14:56:50 +0100 |
commit | a3b4e43dd86de12c1e2ca403f0535eaa3ef21497 (patch) | |
tree | 9b54585ee6892b31c4e7fc8e28fab9863e41e864 /Userland | |
parent | a49c77b76d0203a0165f3749c290ef363fbddd44 (diff) | |
download | serenity-a3b4e43dd86de12c1e2ca403f0535eaa3ef21497.zip |
LibC: Implement __freading and __fwriting
These functions are used by gnulib (and therefore many GNU utilities)
to provide access to internal details of the stdio FILE structure.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibC/stdio.cpp | 41 | ||||
-rw-r--r-- | Userland/Libraries/LibC/stdio_ext.h | 16 |
2 files changed, 57 insertions, 0 deletions
diff --git a/Userland/Libraries/LibC/stdio.cpp b/Userland/Libraries/LibC/stdio.cpp index 2d3aa0bfc8..6eca1a2bb0 100644 --- a/Userland/Libraries/LibC/stdio.cpp +++ b/Userland/Libraries/LibC/stdio.cpp @@ -16,6 +16,7 @@ #include <fcntl.h> #include <stdarg.h> #include <stdio.h> +#include <stdio_ext.h> #include <stdlib.h> #include <string.h> #include <sys/internals.h> @@ -43,6 +44,8 @@ public: int fileno() const { return m_fd; } bool eof() const { return m_eof; } + int mode() const { return m_mode; } + u8 flags() const { return m_flags; } int error() const { return m_error; } void clear_err() { m_error = 0; } @@ -61,6 +64,12 @@ public: void reopen(int fd, int mode); + enum Flags : u8 { + None = 0, + LastRead = 1, + LastWrite = 2, + }; + private: struct Buffer { // A ringbuffer that also transparently implements ungetc(). @@ -117,6 +126,7 @@ private: int m_fd { -1 }; int m_mode { 0 }; + u8 m_flags { Flags::None }; int m_error { 0 }; bool m_eof { false }; pid_t m_popen_child { -1 }; @@ -241,6 +251,9 @@ size_t FILE::read(u8* data, size_t size) { size_t total_read = 0; + m_flags |= Flags::LastRead; + m_flags &= ~Flags::LastWrite; + while (size > 0) { size_t actual_size; @@ -280,6 +293,9 @@ size_t FILE::write(const u8* data, size_t size) { size_t total_written = 0; + m_flags &= ~Flags::LastRead; + m_flags |= Flags::LastWrite; + while (size > 0) { size_t actual_size; @@ -332,6 +348,9 @@ bool FILE::gets(u8* data, size_t size) if (size == 0) return false; + m_flags |= Flags::LastRead; + m_flags &= ~Flags::LastWrite; + while (size > 1) { if (m_buffer.may_use()) { // Let's see if the buffer has something queued for us. @@ -1282,4 +1301,26 @@ FILE* tmpfile() unlink(tmp_path); return fdopen(fd, "rw"); } + +int __freading(FILE* stream) +{ + ScopedFileLock lock(stream); + + if ((stream->mode() & O_RDWR) == O_RDONLY) { + return 1; + } + + return (stream->flags() & FILE::Flags::LastRead); +} + +int __fwriting(FILE* stream) +{ + ScopedFileLock lock(stream); + + if ((stream->mode() & O_RDWR) == O_WRONLY) { + return 1; + } + + return (stream->flags() & FILE::Flags::LastWrite); +} } diff --git a/Userland/Libraries/LibC/stdio_ext.h b/Userland/Libraries/LibC/stdio_ext.h new file mode 100644 index 0000000000..f9f8b5a18b --- /dev/null +++ b/Userland/Libraries/LibC/stdio_ext.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, the SerenityOS developers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <stdio.h> + +__BEGIN_DECLS + +int __freading(FILE*); +int __fwriting(FILE*); + +__END_DECLS |