apio
44815b08c7
This is huge. Finally, we can do proper reads/writes with invalid addresses, or big buffers.
96 lines
2.6 KiB
C++
96 lines
2.6 KiB
C++
#include "fs/FileDescriptor.h"
|
|
#include "std/errno.h"
|
|
#include "std/stdlib.h"
|
|
#include "sys/UserMemory.h"
|
|
|
|
Descriptor::Descriptor() : m_is_open(false)
|
|
{
|
|
}
|
|
|
|
Descriptor::Descriptor(const Descriptor& other)
|
|
: m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write),
|
|
m_able_to_block(other.m_able_to_block), m_close_on_exec(other.m_close_on_exec), m_node(other.m_node),
|
|
m_offset(other.m_offset)
|
|
{
|
|
}
|
|
|
|
void Descriptor::open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec)
|
|
{
|
|
m_can_read = can_read;
|
|
m_can_write = can_write;
|
|
m_able_to_block = able_to_block;
|
|
m_close_on_exec = close_on_exec;
|
|
m_node = node;
|
|
m_offset = 0;
|
|
m_is_open = true;
|
|
}
|
|
|
|
ssize_t Descriptor::read(size_t size, char* buffer)
|
|
{
|
|
ssize_t result = VFS::read(m_node, m_offset, size, buffer);
|
|
m_offset += result;
|
|
return result;
|
|
}
|
|
|
|
ssize_t Descriptor::write(size_t size, const char* buffer)
|
|
{
|
|
ssize_t result = VFS::write(m_node, m_offset, size, buffer);
|
|
m_offset += result;
|
|
return result;
|
|
}
|
|
|
|
ssize_t Descriptor::user_read(size_t size, char* buffer)
|
|
{
|
|
char* buf = (char*)kmalloc(size);
|
|
if (!buf) return -ENOMEM;
|
|
ssize_t result = read(size, buf);
|
|
if (!copy_to_user(buffer, buf, size)) result = -EFAULT;
|
|
kfree(buf);
|
|
return result;
|
|
}
|
|
|
|
ssize_t Descriptor::user_write(size_t size, const char* buffer)
|
|
{
|
|
char* buf = (char*)kmalloc(size);
|
|
if (!buf) return -ENOMEM;
|
|
ssize_t result;
|
|
if (!copy_from_user(buffer, buf, size)) result = -EFAULT;
|
|
else
|
|
result = write(size, buf);
|
|
kfree(buf);
|
|
return result;
|
|
}
|
|
|
|
#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno)
|
|
|
|
uintptr_t Descriptor::mmap(uintptr_t addr, size_t size, int prot, off_t offset)
|
|
{
|
|
if (!m_node->mmap_func) return MAP_FAIL(ENOTSUP);
|
|
return m_node->mmap_func(m_node, addr, size, prot, offset);
|
|
}
|
|
|
|
long Descriptor::ioctl(int cmd, uintptr_t arg)
|
|
{
|
|
if (!m_node->ioctl_func) return MAP_FAIL(ENOTSUP);
|
|
return m_node->ioctl_func(m_node, cmd, arg);
|
|
}
|
|
|
|
int Descriptor::seek(long offset)
|
|
{
|
|
if (m_node->type == VFS_FILE && (uint64_t)offset > m_node->length)
|
|
return -EINVAL; // FIXME: Support seeking beyond the current file's length.
|
|
m_offset = (uint64_t)offset;
|
|
return 0;
|
|
}
|
|
|
|
const Descriptor& Descriptor::operator=(const Descriptor& other)
|
|
{
|
|
m_is_open = other.m_is_open;
|
|
m_can_read = other.m_can_read;
|
|
m_can_write = other.m_can_write;
|
|
m_offset = other.m_offset;
|
|
m_node = other.m_node;
|
|
m_able_to_block = other.m_able_to_block;
|
|
m_close_on_exec = other.m_close_on_exec;
|
|
return other;
|
|
} |