Kernel: Remove offset from OpenFileDescriptor

This is now handled on the libc side. There might be reasons to
have it in kernel side, but for simplicity's sake I'm moving it
to libc for now :)
This commit is contained in:
Bananymous 2023-05-09 20:31:22 +03:00
parent 0cc1fb53d5
commit ff2e2937a5
12 changed files with 90 additions and 142 deletions

View File

@ -25,7 +25,7 @@ namespace LibELF
TRY(data.resize(st.st_size)); TRY(data.resize(st.st_size));
TRY(Kernel::Process::current().read(fd, data.data(), data.size())); TRY(Kernel::Process::current().read(fd, data.data(), 0, data.size()));
elf = new ELF(BAN::move(data)); elf = new ELF(BAN::move(data));
ASSERT(elf); ASSERT(elf);

View File

@ -153,9 +153,13 @@ irq 13
irq 14 irq 14
irq 15 irq 15
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
.global syscall_asm .global syscall_asm
syscall_asm: syscall_asm:
pushaq pushaq
movq %rsi, %r8
movq %rdi, %r9
movq %rax, %rdi movq %rax, %rdi
movq %rbx, %rsi movq %rbx, %rsi
xchgq %rcx, %rdx xchgq %rcx, %rdx

View File

@ -41,16 +41,15 @@ namespace Kernel
pid_t pid() const { return m_pid; } pid_t pid() const { return m_pid; }
BAN::ErrorOr<int> open(BAN::StringView, int); BAN::ErrorOr<int> open(BAN::StringView, int);
BAN::ErrorOr<void> close(int); BAN::ErrorOr<void> close(int fd);
BAN::ErrorOr<size_t> read(int, void*, size_t); BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t offset, size_t count);
BAN::ErrorOr<size_t> write(int, const void*, size_t); BAN::ErrorOr<size_t> write(int fd, const void* buffer, size_t offset, size_t count);
BAN::ErrorOr<void> creat(BAN::StringView, mode_t); BAN::ErrorOr<void> creat(BAN::StringView name, mode_t);
BAN::ErrorOr<void> seek(int, size_t);
BAN::ErrorOr<void> fstat(int, stat*); BAN::ErrorOr<void> fstat(int fd, stat*);
BAN::ErrorOr<void> stat(BAN::StringView, stat*); BAN::ErrorOr<void> stat(BAN::StringView path, stat*);
BAN::ErrorOr<void> mount(BAN::StringView, BAN::StringView); BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target);
BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries(int); BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries(int);
@ -78,7 +77,6 @@ namespace Kernel
{ {
BAN::RefPtr<Inode> inode; BAN::RefPtr<Inode> inode;
BAN::String path; BAN::String path;
size_t offset = 0;
uint8_t flags = 0; uint8_t flags = 0;
}; };

View File

@ -5,21 +5,20 @@
#define SYS_WRITE 3 #define SYS_WRITE 3
#define SYS_TERMID 4 #define SYS_TERMID 4
#define SYS_CLOSE 5 #define SYS_CLOSE 5
#define SYS_SEEK 6 #define SYS_OPEN 6
#define SYS_OPEN 7 #define SYS_ALLOC 7
#define SYS_ALLOC 8 #define SYS_FREE 8
#define SYS_FREE 9
#include <kernel/Attributes.h>
#include <stdint.h> #include <stdint.h>
namespace Kernel namespace Kernel
{ {
template<typename T1 = void*, typename T2 = void*, typename T3 = void*> ALWAYS_INLINE long syscall(int syscall, uintptr_t arg1 = 0, uintptr_t arg2 = 0, uintptr_t arg3 = 0, uintptr_t arg4 = 0, uintptr_t arg5 = 0)
inline long syscall(int syscall, T1 arg1 = nullptr, T2 arg2 = nullptr, T3 arg3 = nullptr)
{ {
long ret; long ret;
asm volatile("int $0x80" : "=a"(ret) : "a"(syscall), "b"((uintptr_t)arg1), "c"((uintptr_t)arg2), "d"((uintptr_t)arg3) : "memory"); asm volatile("int $0x80" : "=a"(ret) : "a"(syscall), "b"((uintptr_t)arg1), "c"((uintptr_t)arg2), "d"((uintptr_t)arg3), "S"((uintptr_t)arg4), "D"((uintptr_t)arg5) : "memory");
return ret; return ret;
} }

View File

@ -45,7 +45,7 @@ namespace Kernel
BAN::Vector<uint8_t> file_data; BAN::Vector<uint8_t> file_data;
TRY(file_data.resize(st.st_size)); TRY(file_data.resize(st.st_size));
TRY(Process::current().read(fd, file_data.data(), st.st_size)); TRY(Process::current().read(fd, file_data.data(), 0, st.st_size));
if (file_data.size() < 4) if (file_data.size() < 4)
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);

View File

@ -202,7 +202,6 @@ namespace Kernel
auto& open_file_description = m_open_files[fd]; auto& open_file_description = m_open_files[fd];
open_file_description.inode = file.inode; open_file_description.inode = file.inode;
open_file_description.path = BAN::move(file.canonical_path); open_file_description.path = BAN::move(file.canonical_path);
open_file_description.offset = 0;
open_file_description.flags = flags; open_file_description.flags = flags;
return fd; return fd;
@ -217,7 +216,7 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<size_t> Process::read(int fd, void* buffer, size_t count) BAN::ErrorOr<size_t> Process::read(int fd, void* buffer, size_t offset, size_t count)
{ {
OpenFileDescription open_fd_copy; OpenFileDescription open_fd_copy;
@ -229,18 +228,10 @@ namespace Kernel
if (!(open_fd_copy.flags & O_RDONLY)) if (!(open_fd_copy.flags & O_RDONLY))
return BAN::Error::from_errno(EBADF); return BAN::Error::from_errno(EBADF);
size_t n_read = TRY(open_fd_copy.inode->read(open_fd_copy.offset, buffer, count)); return TRY(open_fd_copy.inode->read(offset, buffer, count));
open_fd_copy.offset += n_read;
m_lock.lock();
MUST(validate_fd(fd));
open_file_description(fd) = open_fd_copy;
m_lock.unlock();
return n_read;
} }
BAN::ErrorOr<size_t> Process::write(int fd, const void* buffer, size_t count) BAN::ErrorOr<size_t> Process::write(int fd, const void* buffer, size_t offset, size_t count)
{ {
OpenFileDescription open_fd_copy; OpenFileDescription open_fd_copy;
@ -252,16 +243,7 @@ namespace Kernel
if (!(open_fd_copy.flags & O_WRONLY)) if (!(open_fd_copy.flags & O_WRONLY))
return BAN::Error::from_errno(EBADF); return BAN::Error::from_errno(EBADF);
size_t n_written = TRY(open_fd_copy.inode->write(open_fd_copy.offset, buffer, count)); return TRY(open_fd_copy.inode->write(offset, buffer, count));
open_fd_copy.offset += n_written;
{
LockGuard _(m_lock);
MUST(validate_fd(fd));
open_file_description(fd) = open_fd_copy;
}
return n_written;
} }
BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode) BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode)
@ -282,11 +264,11 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> Process::mount(BAN::StringView partition, BAN::StringView path) BAN::ErrorOr<void> Process::mount(BAN::StringView source, BAN::StringView target)
{ {
auto absolute_partition = TRY(absolute_path_of(partition)); auto absolute_source = TRY(absolute_path_of(source));
auto absolute_path = TRY(absolute_path_of(path)); auto absolute_target = TRY(absolute_path_of(target));
TRY(VirtualFileSystem::get().mount(absolute_partition, absolute_path)); TRY(VirtualFileSystem::get().mount(absolute_source, absolute_target));
return {}; return {};
} }
@ -325,15 +307,7 @@ namespace Kernel
return ret; return ret;
} }
BAN::ErrorOr<void> Process::seek(int fd, size_t offset) // FIXME: This whole API has to be rewritten
{
LockGuard _(m_lock);
TRY(validate_fd(fd));
auto& open_fd = open_file_description(fd);
open_fd.offset = offset;
return {};
}
BAN::ErrorOr<BAN::Vector<BAN::String>> Process::read_directory_entries(int fd) BAN::ErrorOr<BAN::Vector<BAN::String>> Process::read_directory_entries(int fd)
{ {
OpenFileDescription open_fd_copy; OpenFileDescription open_fd_copy;
@ -344,15 +318,7 @@ namespace Kernel
open_fd_copy = open_file_description(fd); open_fd_copy = open_file_description(fd);
} }
auto result = TRY(open_fd_copy.inode->read_directory_entries(open_fd_copy.offset)); return TRY(open_fd_copy.inode->read_directory_entries(0));
open_fd_copy.offset++;
m_lock.lock();
MUST(validate_fd(fd));
open_file_description(fd) = open_fd_copy;
m_lock.unlock();
return result;
} }
BAN::ErrorOr<BAN::String> Process::working_directory() const BAN::ErrorOr<BAN::String> Process::working_directory() const

View File

@ -22,14 +22,14 @@ namespace Kernel
static void TTY_PRINT(Args&&... args) static void TTY_PRINT(Args&&... args)
{ {
BAN::String message = BAN::String::formatted(BAN::forward<Args>(args)...); BAN::String message = BAN::String::formatted(BAN::forward<Args>(args)...);
MUST(Process::current().write(STDOUT_FILENO, message.data(), message.size())); MUST(Process::current().write(STDOUT_FILENO, message.data(), 0, message.size()));
} }
template<typename... Args> template<typename... Args>
static void TTY_PRINTLN(Args&&... args) static void TTY_PRINTLN(Args&&... args)
{ {
TTY_PRINT(BAN::forward<Args>(args)...); TTY_PRINT(BAN::forward<Args>(args)...);
MUST(Process::current().write(STDOUT_FILENO, "\n", 1)); MUST(Process::current().write(STDOUT_FILENO, "\n", 0, 1));
} }
static auto s_default_prompt = "\\[\e[32m\\]user\\[\e[m\\]:\\[\e[34m\\]\\w\\[\e[m\\]# "sv; static auto s_default_prompt = "\\[\e[32m\\]user\\[\e[m\\]:\\[\e[34m\\]\\w\\[\e[m\\]# "sv;
@ -112,7 +112,7 @@ namespace Kernel
void Shell::run() void Shell::run()
{ {
auto getch = [this] { uint8_t ch; MUST(Process::current().read(STDIN_FILENO, &ch, 1)); return ch; }; auto getch = [this] { uint8_t ch; MUST(Process::current().read(STDIN_FILENO, &ch, 0, 1)); return ch; };
MUST(m_buffer.push_back(""sv)); MUST(m_buffer.push_back(""sv));
@ -130,7 +130,7 @@ namespace Kernel
while ((current.back() & 0xC0) == 0x80) while ((current.back() & 0xC0) == 0x80)
current.pop_back(); current.pop_back();
current.pop_back(); current.pop_back();
MUST(Process::current().write(STDOUT_FILENO, "\b \b", 3)); MUST(Process::current().write(STDOUT_FILENO, "\b \b", 0, 3));
} }
continue; continue;
} }
@ -171,7 +171,7 @@ namespace Kernel
continue; continue;
} }
MUST(Process::current().write(STDOUT_FILENO, &ch, 1)); MUST(Process::current().write(STDOUT_FILENO, &ch, 0, 1));
if (ch != '\n') if (ch != '\n')
{ {
@ -556,8 +556,12 @@ argument_done:
BAN::ScopeGuard buffer_guard([buffer] { delete[] buffer; }); BAN::ScopeGuard buffer_guard([buffer] { delete[] buffer; });
ASSERT(buffer); ASSERT(buffer);
while (size_t n_read = TRY(Process::current().read(fd, buffer, buffer_size))) size_t offset = 0;
while (size_t n_read = TRY(Process::current().read(fd, buffer, offset, buffer_size)))
{
TTY_PRINT("{}", BAN::StringView(buffer, n_read)); TTY_PRINT("{}", BAN::StringView(buffer, n_read));
offset += n_read;
}
TTY_PRINTLN(""); TTY_PRINTLN("");
} }
else if (arguments.front() == "stat") else if (arguments.front() == "stat")
@ -635,7 +639,7 @@ argument_done:
while (true) while (true)
{ {
size_t n_read = TRY(Process::current().read(fd, buffer, buffer_size)); size_t n_read = TRY(Process::current().read(fd, buffer, total_read, buffer_size));
if (n_read == 0) if (n_read == 0)
break; break;
for (size_t j = 0; j < n_read; j++) for (size_t j = 0; j < n_read; j++)

View File

@ -10,17 +10,17 @@ namespace Kernel
Process::current().exit(); Process::current().exit();
} }
long sys_read(int fd, void* buffer, size_t size) long sys_read(int fd, void* buffer, size_t offset, size_t size)
{ {
auto res = Process::current().read(fd, buffer, size); auto res = Process::current().read(fd, buffer, offset, size);
if (res.is_error()) if (res.is_error())
return -res.error().get_error_code(); return -res.error().get_error_code();
return res.value(); return res.value();
} }
long sys_write(int fd, const void* buffer, size_t size) long sys_write(int fd, const void* buffer, size_t offset, size_t size)
{ {
auto res = Process::current().write(fd, buffer, size); auto res = Process::current().write(fd, buffer, offset, size);
if (res.is_error()) if (res.is_error())
return -res.error().get_error_code(); return -res.error().get_error_code();
return res.value(); return res.value();
@ -34,14 +34,6 @@ namespace Kernel
return 0; return 0;
} }
int sys_seek(int fd, long offset)
{
auto res = Process::current().seek(fd, offset);
if (res.is_error())
return -res.error().get_error_code();
return 0;
}
void sys_termid(char* buffer) void sys_termid(char* buffer)
{ {
Process::current().termid(buffer); Process::current().termid(buffer);
@ -68,12 +60,14 @@ namespace Kernel
Process::current().free(ptr); Process::current().free(ptr);
} }
extern "C" long cpp_syscall_handler(int syscall, void* arg1, void* arg2, void* arg3) extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5)
{ {
Thread::current().set_in_syscall(true); Thread::current().set_in_syscall(true);
asm volatile("sti"); asm volatile("sti");
(void)arg5;
long ret = 0; long ret = 0;
switch (syscall) switch (syscall)
{ {
@ -81,28 +75,25 @@ namespace Kernel
sys_exit(); sys_exit();
break; break;
case SYS_READ: case SYS_READ:
ret = sys_read((int)(uintptr_t)arg1, arg2, (size_t)(uintptr_t)arg3); ret = sys_read((int)arg1, (void*)arg2, (size_t)arg3, (size_t)arg4);
break; break;
case SYS_WRITE: case SYS_WRITE:
ret = sys_write((int)(uintptr_t)arg1, arg2, (size_t)(uintptr_t)arg3); ret = sys_write((int)arg1, (const void*)arg2, (size_t)arg3, (size_t)arg4);
break; break;
case SYS_TERMID: case SYS_TERMID:
sys_termid((char*)arg1); sys_termid((char*)arg1);
break; break;
case SYS_CLOSE: case SYS_CLOSE:
ret = sys_close((int)(uintptr_t)arg1); ret = sys_close((int)arg1);
break;
case SYS_SEEK:
ret = sys_seek((int)(uintptr_t)arg1, (long)arg2);
break; break;
case SYS_OPEN: case SYS_OPEN:
ret = sys_open((const char*)arg1, (int)(uintptr_t)arg2); ret = sys_open((const char*)arg1, (int)arg2);
break; break;
case SYS_ALLOC: case SYS_ALLOC:
ret = sys_alloc((size_t)arg1); ret = sys_alloc((size_t)arg1);
break; break;
case SYS_FREE: case SYS_FREE:
sys_free(arg1); sys_free((void*)arg1);
break; break;
default: default:
Kernel::panic("Unknown syscall {}", syscall); Kernel::panic("Unknown syscall {}", syscall);

View File

@ -66,7 +66,7 @@ namespace Kernel
while (true) while (true)
{ {
Input::KeyEvent event; Input::KeyEvent event;
ASSERT(MUST(Process::current().read(fd, &event, sizeof(event))) == sizeof(event)); ASSERT(MUST(Process::current().read(fd, &event, 0, sizeof(event))) == sizeof(event));
TTY::current()->on_key(event); TTY::current()->on_key(event);
} }
}, nullptr }, nullptr

View File

@ -76,7 +76,7 @@ int fflush(FILE* file)
if (file->buffer_index == 0) if (file->buffer_index == 0)
return 0; return 0;
if (syscall(SYS_WRITE, file->fd, file->buffer, file->buffer_index) < 0) if (syscall(SYS_WRITE, file->fd, file->buffer, file->offset, file->buffer_index) < 0)
{ {
file->error = true; file->error = true;
return EOF; return EOF;
@ -92,7 +92,7 @@ int fgetc(FILE* file)
return EOF; return EOF;
unsigned char c; unsigned char c;
long ret = syscall(SYS_READ, file->fd, &c, 1); long ret = syscall(SYS_READ, file->fd, &c, file->offset, 1);
if (ret < 0) if (ret < 0)
{ {
@ -235,7 +235,7 @@ size_t fread(void* buffer, size_t size, size_t nitems, FILE* file)
{ {
if (file->eof || nitems * size == 0) if (file->eof || nitems * size == 0)
return 0; return 0;
long ret = syscall(SYS_READ, file->fd, buffer, size * nitems); long ret = syscall(SYS_READ, file->fd, buffer, file->offset, size * nitems);
if (ret < 0) if (ret < 0)
{ {
file->error = true; file->error = true;
@ -260,7 +260,13 @@ int fseek(FILE* file, long offset, int whence)
int fseeko(FILE* file, off_t offset, int whence) int fseeko(FILE* file, off_t offset, int whence)
{ {
if (whence == SEEK_CUR) if (offset < 0)
{
errno = EINVAL;
return -1;
}
if (whence == SEEK_CUR && offset <= file->offset)
file->offset += offset; file->offset += offset;
else if (whence == SEEK_SET) else if (whence == SEEK_SET)
file->offset = offset; file->offset = offset;
@ -275,16 +281,6 @@ int fseeko(FILE* file, off_t offset, int whence)
return -1; return -1;
} }
if (file->offset < 0)
{
file->offset -= offset;
errno = EINVAL;
return -1;
}
if (syscall(SYS_SEEK, file->fd, file->offset))
return -1;
file->eof = false; file->eof = false;
return 0; return 0;

View File

@ -31,22 +31,24 @@ long syscall(long syscall, ...)
{ {
int fd = va_arg(args, int); int fd = va_arg(args, int);
void* buffer = va_arg(args, void*); void* buffer = va_arg(args, void*);
size_t offset = va_arg(args, size_t);
size_t bytes = va_arg(args, size_t); size_t bytes = va_arg(args, size_t);
ret = Kernel::syscall(SYS_READ, fd, buffer, bytes); ret = Kernel::syscall(SYS_READ, fd, (uintptr_t)buffer, offset, bytes);
break; break;
} }
case SYS_WRITE: case SYS_WRITE:
{ {
int fd = va_arg(args, int); int fd = va_arg(args, int);
const char* string = va_arg(args, const char*); const char* string = va_arg(args, const char*);
size_t offset = va_arg(args, size_t);
size_t bytes = va_arg(args, size_t); size_t bytes = va_arg(args, size_t);
ret = Kernel::syscall(SYS_WRITE, fd, string, bytes); ret = Kernel::syscall(SYS_WRITE, fd, (uintptr_t)string, offset, bytes);
break; break;
} }
case SYS_TERMID: case SYS_TERMID:
{ {
char* buffer = va_arg(args, char*); char* buffer = va_arg(args, char*);
ret = Kernel::syscall(SYS_TERMID, buffer); ret = Kernel::syscall(SYS_TERMID, (uintptr_t)buffer);
break; break;
} }
case SYS_CLOSE: case SYS_CLOSE:
@ -55,18 +57,11 @@ long syscall(long syscall, ...)
ret = Kernel::syscall(SYS_CLOSE, fd); ret = Kernel::syscall(SYS_CLOSE, fd);
break; break;
} }
case SYS_SEEK:
{
int fd = va_arg(args, int);
long offset = va_arg(args, long);
ret = Kernel::syscall(SYS_SEEK, fd, offset);
break;
}
case SYS_OPEN: case SYS_OPEN:
{ {
const char* path = va_arg(args, const char*); const char* path = va_arg(args, const char*);
int oflags = va_arg(args, int); int oflags = va_arg(args, int);
ret = Kernel::syscall(SYS_OPEN, path, oflags); ret = Kernel::syscall(SYS_OPEN, (uintptr_t)path, oflags);
break; break;
} }
case SYS_ALLOC: case SYS_ALLOC:
@ -78,7 +73,7 @@ long syscall(long syscall, ...)
case SYS_FREE: case SYS_FREE:
{ {
void* ptr = va_arg(args, void*); void* ptr = va_arg(args, void*);
ret = Kernel::syscall(SYS_FREE, ptr); ret = Kernel::syscall(SYS_FREE, (uintptr_t)ptr);
break; break;
} }
default: default:

View File

@ -1,35 +1,30 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define N 1024 #define ERROR(msg) { perror(msg); return 1; }
#define BUF_SIZE 1024
int main() int main()
{ {
for (int i = 0; i <= 10; i++) FILE* fp = fopen("/usr/include/stdio.h", "r");
{ if (fp == NULL)
int** ptrs = malloc(N * sizeof(int*)); ERROR("fopen");
if (ptrs == NULL)
{
perror("malloc");
return 1;
}
for (int j = 0; j < N; j++)
{
ptrs[j] = malloc(sizeof(int));
if (ptrs[j] == NULL)
{
perror("malloc");
return 1;
}
*ptrs[j] = j;
putchar('0' + *ptrs[j] % 10);
}
putchar('\n');
for (int j = 0; j < N; j++) char* buffer = malloc(BUF_SIZE);
free(ptrs[j]); if (buffer == NULL)
free(ptrs); ERROR("malloc");
for (;;)
{
size_t n_read = fread(buffer, 1, BUF_SIZE - 1, fp);
if (n_read == 0)
break;
buffer[n_read] = '\0';
printf("%s", buffer);
} }
free(buffer);
fclose(fp);
return 0; return 0;
} }