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/SharedPtr.h>
#include <luna/StringView.h> #include <luna/StringView.h>
#include <os/Path.h> #include <os/Path.h>
#include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
namespace os namespace os
@ -164,9 +165,14 @@ namespace os
*/ */
int fd() const 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. * @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_read(u8* buf, usize length);
Result<usize> raw_write(const 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 <luna/StringBuilder.h>
#include <os/File.h> #include <os/File.h>
#include <sys/syscall.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_stdout = {};
static SharedPtr<os::File> g_stderr = {}; 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 namespace os
{ {
File::File(Badge<File>) File::File(Badge<File>)
@ -24,22 +40,22 @@ namespace os
File::~File() File::~File()
{ {
if (m_fd >= 0) close(m_fd); if (m_file) fclose(m_file);
} }
void File::initialize_standard_streams() void File::initialize_standard_streams()
{ {
g_stdin = adopt_shared_if_nonnull(new (std::nothrow) File({})) g_stdin = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard input stream"); .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({})) g_stdout = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard output stream"); .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({})) g_stderr = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard error stream"); .expect_release_value("Cannot open standard error stream");
g_stderr->m_fd = STDERR_FILENO; g_stderr->m_file = stderr;
} }
SharedPtr<File> File::standard_input() SharedPtr<File> File::standard_input()
@ -70,7 +86,8 @@ namespace os
long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode); long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode);
int fd = TRY(Result<int>::from_syscall(rc)); 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; return file;
} }
@ -99,14 +116,16 @@ namespace os
Result<usize> File::raw_read(u8* buf, usize length) Result<usize> File::raw_read(u8* buf, usize length)
{ {
long rc = syscall(SYS_read, m_fd, buf, length); size_t nread = fread(buf, 1, length, m_file);
return Result<usize>::from_syscall(rc); if (nread == 0 && ferror(m_file)) return err(errno);
return nread;
} }
Result<usize> File::raw_write(const u8* buf, usize length) Result<usize> File::raw_write(const u8* buf, usize length)
{ {
long rc = syscall(SYS_write, m_fd, buf, length); size_t nwrite = fwrite(buf, 1, length, m_file);
return Result<usize>::from_syscall(rc); if (nwrite == 0 && ferror(m_file)) return err(errno);
return nwrite;
} }
Result<void> File::write(StringView str) Result<void> File::write(StringView str)
@ -130,7 +149,7 @@ namespace os
int current; int current;
while (true) while (true)
{ {
current = TRY(getchar()); current = fgetc(m_file);
if (current == -1) break; if (current == -1) break;
@ -189,29 +208,31 @@ namespace os
Result<int> File::getchar() Result<int> File::getchar()
{ {
u8 value; return fgetc(m_file);
usize nread = TRY(raw_read(&value, 1));
if (!nread) return -1;
return value;
} }
void File::set_close_on_exec() void File::set_close_on_exec()
{ {
fcntl(m_fd, F_SETFD, FD_CLOEXEC); fcntl(fd(), F_SETFD, FD_CLOEXEC);
} }
void File::rewind() 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. // FIXME: Do not allocate memory for printing.
Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap) Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap)
{ {
auto str = TRY(String::vformat(fmt, 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, ...) Result<void> print(StringView fmt, ...)