libos: Make os::File a wrapper around stdio's FILE
All checks were successful
continuous-integration/drone/push Build is passing
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:
parent
358493a7bc
commit
eeb9e16a74
@ -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 };
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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, ...)
|
||||
|
Loading…
Reference in New Issue
Block a user