diff --git a/libos/include/os/File.h b/libos/include/os/File.h index 5e54b556..1e280dce 100644 --- a/libos/include/os/File.h +++ b/libos/include/os/File.h @@ -14,6 +14,7 @@ #include #include #include +#include #include 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 raw_read(u8* buf, usize length); Result raw_write(const u8* buf, usize length); - int m_fd { -1 }; + FILE* m_file { nullptr }; }; /** diff --git a/libos/src/File.cpp b/libos/src/File.cpp index 3e0f2f46..f7a9448d 100644 --- a/libos/src/File.cpp +++ b/libos/src/File.cpp @@ -7,6 +7,7 @@ * */ +#include #include #include #include @@ -16,6 +17,21 @@ static SharedPtr g_stdin = {}; static SharedPtr g_stdout = {}; static SharedPtr 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) @@ -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::standard_input() @@ -70,7 +86,8 @@ namespace os long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode); int fd = TRY(Result::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 File::raw_read(u8* buf, usize length) { - long rc = syscall(SYS_read, m_fd, buf, length); - return Result::from_syscall(rc); + size_t nread = fread(buf, 1, length, m_file); + if (nread == 0 && ferror(m_file)) return err(errno); + return nread; } Result File::raw_write(const u8* buf, usize length) { - long rc = syscall(SYS_write, m_fd, buf, length); - return Result::from_syscall(rc); + size_t nwrite = fwrite(buf, 1, length, m_file); + if (nwrite == 0 && ferror(m_file)) return err(errno); + return nwrite; } Result 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 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 print_impl(SharedPtr 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 print(StringView fmt, ...)