Luna/libos/src/File.cpp

190 lines
4.3 KiB
C++
Raw Normal View History

#include <fcntl.h>
#include <luna/StringBuilder.h>
#include <os/File.h>
#include <sys/syscall.h>
#include <unistd.h>
static SharedPtr<os::File> g_stdin = {};
static SharedPtr<os::File> g_stdout = {};
static SharedPtr<os::File> g_stderr = {};
namespace os
{
File::File(Badge<File>)
{
}
File::~File()
{
if (m_fd >= 0) close(m_fd);
}
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_stdout = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard output stream");
g_stdout->m_fd = STDOUT_FILENO;
g_stderr = adopt_shared_if_nonnull(new (std::nothrow) File({}))
.expect_release_value("Cannot open standard error stream");
g_stderr->m_fd = STDERR_FILENO;
}
SharedPtr<File> File::standard_input()
{
if (!g_stdin) initialize_standard_streams();
return g_stdin;
}
SharedPtr<File> File::standard_output()
{
if (!g_stdout) initialize_standard_streams();
return g_stdout;
}
SharedPtr<File> File::standard_error()
{
if (!g_stderr) initialize_standard_streams();
return g_stderr;
}
Result<SharedPtr<File>> File::construct(StringView path, int flags, mode_t mode)
{
auto file = TRY(adopt_shared_if_nonnull(new (std::nothrow) File({})));
long rc = syscall(SYS_openat, AT_FDCWD, path.chars(), flags, mode);
int fd = TRY(Result<int>::from_syscall(rc));
file->m_fd = fd;
return file;
}
Result<SharedPtr<File>> File::open(StringView path, OpenMode flags)
{
return construct(path, (int)flags, 0);
}
Result<SharedPtr<File>> File::open_or_create(StringView path, OpenMode flags, mode_t mode)
{
return construct(path, (int)flags | O_CREAT, mode);
}
Result<SharedPtr<File>> File::create(StringView path, OpenMode flags, mode_t mode)
{
return construct(path, (int)flags | (O_CREAT | O_EXCL), mode);
}
Result<usize> File::raw_read(u8* buf, usize length)
{
long rc = syscall(SYS_read, m_fd, buf, length);
return Result<usize>::from_syscall(rc);
}
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);
}
Result<void> File::write(StringView str)
{
TRY(raw_write((const u8*)str.chars(), str.length()));
return {};
}
Result<void> File::write(const Buffer& buf)
{
TRY(raw_write(buf.data(), buf.size()));
return {};
}
Result<String> File::read_line()
{
Vector<char> data;
int current;
while (true)
{
current = TRY(getchar());
if (current == -1) break;
TRY(data.try_append((char)current));
if (current == '\n') break;
}
if (!data.size()) return String {};
TRY(data.try_append('\0'));
return String::from_cstring(data.data());
}
Result<String> File::read_all_as_string()
{
StringBuilder sb;
while (true)
{
auto line = TRY(read_line());
if (line.is_empty()) break;
TRY(sb.add(line));
}
return sb.string();
}
Result<Buffer> File::read_all()
{
Vector<u8> data;
while (true)
{
int c = TRY(getchar());
if (c == -1) break;
TRY(data.try_append((u8)c));
}
Buffer buf;
TRY(buf.append_data(data.data(), data.size()));
return buf;
}
Result<void> File::read(Buffer& buf, usize size)
{
u8* slice = TRY(buf.slice(0, size));
usize nread = TRY(raw_read(slice, size));
TRY(buf.try_resize(nread));
return {};
}
Result<int> File::getchar()
{
u8 value;
usize nread = TRY(raw_read(&value, 1));
if (!nread) return -1;
return value;
}
void File::set_close_on_exec()
{
fcntl(m_fd, F_SETFD, FD_CLOEXEC);
}
}