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.
This commit is contained in:
Tim Schumacher 2021-05-26 08:39:19 +02:00 committed by Linus Groh
parent a49c77b76d
commit a3b4e43dd8
Notes: sideshowbarker 2024-07-18 17:10:04 +09:00
2 changed files with 57 additions and 0 deletions

View File

@ -16,6 +16,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/internals.h> #include <sys/internals.h>
@ -43,6 +44,8 @@ public:
int fileno() const { return m_fd; } int fileno() const { return m_fd; }
bool eof() const { return m_eof; } bool eof() const { return m_eof; }
int mode() const { return m_mode; }
u8 flags() const { return m_flags; }
int error() const { return m_error; } int error() const { return m_error; }
void clear_err() { m_error = 0; } void clear_err() { m_error = 0; }
@ -61,6 +64,12 @@ public:
void reopen(int fd, int mode); void reopen(int fd, int mode);
enum Flags : u8 {
None = 0,
LastRead = 1,
LastWrite = 2,
};
private: private:
struct Buffer { struct Buffer {
// A ringbuffer that also transparently implements ungetc(). // A ringbuffer that also transparently implements ungetc().
@ -117,6 +126,7 @@ private:
int m_fd { -1 }; int m_fd { -1 };
int m_mode { 0 }; int m_mode { 0 };
u8 m_flags { Flags::None };
int m_error { 0 }; int m_error { 0 };
bool m_eof { false }; bool m_eof { false };
pid_t m_popen_child { -1 }; pid_t m_popen_child { -1 };
@ -241,6 +251,9 @@ size_t FILE::read(u8* data, size_t size)
{ {
size_t total_read = 0; size_t total_read = 0;
m_flags |= Flags::LastRead;
m_flags &= ~Flags::LastWrite;
while (size > 0) { while (size > 0) {
size_t actual_size; size_t actual_size;
@ -280,6 +293,9 @@ size_t FILE::write(const u8* data, size_t size)
{ {
size_t total_written = 0; size_t total_written = 0;
m_flags &= ~Flags::LastRead;
m_flags |= Flags::LastWrite;
while (size > 0) { while (size > 0) {
size_t actual_size; size_t actual_size;
@ -332,6 +348,9 @@ bool FILE::gets(u8* data, size_t size)
if (size == 0) if (size == 0)
return false; return false;
m_flags |= Flags::LastRead;
m_flags &= ~Flags::LastWrite;
while (size > 1) { while (size > 1) {
if (m_buffer.may_use()) { if (m_buffer.may_use()) {
// Let's see if the buffer has something queued for us. // Let's see if the buffer has something queued for us.
@ -1282,4 +1301,26 @@ FILE* tmpfile()
unlink(tmp_path); unlink(tmp_path);
return fdopen(fd, "rw"); 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);
}
} }

View File

@ -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