libos: Make os::File a wrapper around stdio's FILE
All checks were successful
continuous-integration/drone/push Build is passing

This way, os::File benefits from the same buffering as stdio.h does.
This commit is contained in:
apio 2023-07-22 12:40:02 +02:00
parent 358493a7bc
commit eeb9e16a74
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 48 additions and 21 deletions

View File

@ -14,6 +14,7 @@
#include <luna/SharedPtr.h>
#include <luna/StringView.h>
#include <os/Path.h>
#include <stdio.h>
#include <sys/types.h>
namespace os
@ -164,9 +165,14 @@ namespace os
*/
int fd() const
{
return m_fd;
return fileno(m_file);
}
/**
* @brief Flushes the stream's buffers.
*/
void flush();
/**
* @brief Move this File's file pointer back to the beginning.
*/
@ -182,7 +188,7 @@ namespace os
Result<usize> raw_read(u8* buf, usize length);
Result<usize> raw_write(const u8* buf, usize length);
int m_fd { -1 };
FILE* m_file { nullptr };
};
/**

View File

@ -7,6 +7,7 @@
*
*/
#include <errno.h>
#include <luna/StringBuilder.h>
#include <os/File.h>
#include <sys/syscall.h>
@ -16,6 +17,21 @@ static SharedPtr<os::File> g_stdin = {};
static SharedPtr<os::File> g_stdout = {};
static SharedPtr<os::File> g_stderr = {};
static const char* stdio_mode_from_openmode(int mode)
{
mode &= ~(O_CREAT | O_EXCL);
switch (mode)
{
case os::File::ReadOnly: return "r";
case os::File::ReadWrite: return "w+";
case os::File::WriteOnly: return "w";
case os::File::ReadAppend: return "a+";
case os::File::Append: return "a";
default: fail("Mode incompatible with fdopen()");
}
}
namespace os
{
File::File(Badge<File>)
@ -24,22 +40,22 @@ namespace os
File::~File()
{
if (m_fd >= 0) close(m_fd);
if (m_file) fclose(m_file);
}
void File::initialize_standard_streams()
{
g_stdin = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard input stream");
g_stdin->m_fd = STDIN_FILENO;
g_stdin->m_file = stdin;
g_stdout = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard output stream");
g_stdout->m_fd = STDOUT_FILENO;
g_stdout->m_file = stdout;
g_stderr = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard error stream");
g_stderr->m_fd = STDERR_FILENO;
g_stderr->m_file = stderr;
}
SharedPtr<File> File::standard_input()
@ -70,7 +86,8 @@ namespace os
long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode);
int fd = TRY(Result<int>::from_syscall(rc));
file->m_fd = fd;
file->m_file = fdopen(fd, stdio_mode_from_openmode(flags));
if (!file->m_file) return err(errno);
return file;
}
@ -99,14 +116,16 @@ namespace os
Result<usize> File::raw_read(u8* buf, usize length)
{
long rc = syscall(SYS_read, m_fd, buf, length);
return Result<usize>::from_syscall(rc);
size_t nread = fread(buf, 1, length, m_file);
if (nread == 0 && ferror(m_file)) return err(errno);
return nread;
}
Result<usize> File::raw_write(const u8* buf, usize length)
{
long rc = syscall(SYS_write, m_fd, buf, length);
return Result<usize>::from_syscall(rc);
size_t nwrite = fwrite(buf, 1, length, m_file);
if (nwrite == 0 && ferror(m_file)) return err(errno);
return nwrite;
}
Result<void> File::write(StringView str)
@ -130,7 +149,7 @@ namespace os
int current;
while (true)
{
current = TRY(getchar());
current = fgetc(m_file);
if (current == -1) break;
@ -189,29 +208,31 @@ namespace os
Result<int> File::getchar()
{
u8 value;
usize nread = TRY(raw_read(&value, 1));
if (!nread) return -1;
return value;
return fgetc(m_file);
}
void File::set_close_on_exec()
{
fcntl(m_fd, F_SETFD, FD_CLOEXEC);
fcntl(fd(), F_SETFD, FD_CLOEXEC);
}
void File::rewind()
{
lseek(m_fd, 0, SEEK_SET);
::rewind(m_file);
}
void File::flush()
{
fflush(m_file);
}
// FIXME: Do not allocate memory for printing.
Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap)
{
auto str = TRY(String::vformat(fmt, ap));
return f->write(str.view());
auto rc = f->write(str.view());
f->flush();
return rc;
}
Result<void> print(StringView fmt, ...)