summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorTim Schumacher <timschumi@gmx.de>2021-05-26 08:39:19 +0200
committerLinus Groh <mail@linusgroh.de>2021-05-30 14:56:50 +0100
commita3b4e43dd86de12c1e2ca403f0535eaa3ef21497 (patch)
tree9b54585ee6892b31c4e7fc8e28fab9863e41e864 /Userland
parenta49c77b76d0203a0165f3749c290ef363fbddd44 (diff)
downloadserenity-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.cpp41
-rw-r--r--Userland/Libraries/LibC/stdio_ext.h16
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