From 4a4a3bf184227a607a67d265e58bfa970bb242db Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 16 May 2023 14:14:47 +0300 Subject: [PATCH] Kernel/LibC: move file offset back to kernel This makes keeping track of offsets easier and more proper --- LibELF/LibELF/ELF.cpp | 2 +- kernel/include/kernel/Process.h | 10 +++-- kernel/include/kernel/Syscall.h | 2 + kernel/kernel/Font.cpp | 2 +- kernel/kernel/Process.cpp | 66 +++++++++++++++++++++++++++++++-- kernel/kernel/Shell.cpp | 18 ++++----- kernel/kernel/Syscall.cpp | 38 ++++++++++++++++--- kernel/kernel/Terminal/TTY.cpp | 2 +- libc/stdio.cpp | 46 ++++++++--------------- libc/unistd.cpp | 14 +++++++ 10 files changed, 142 insertions(+), 58 deletions(-) diff --git a/LibELF/LibELF/ELF.cpp b/LibELF/LibELF/ELF.cpp index 6d696e31..e6bf564c 100644 --- a/LibELF/LibELF/ELF.cpp +++ b/LibELF/LibELF/ELF.cpp @@ -25,7 +25,7 @@ namespace LibELF TRY(data.resize(st.st_size)); - TRY(Kernel::Process::current().read(fd, data.data(), 0, data.size())); + TRY(Kernel::Process::current().read(fd, data.data(), data.size())); elf = new ELF(BAN::move(data)); ASSERT(elf); diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 90f1528c..f25ee6b9 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -42,10 +42,13 @@ namespace Kernel BAN::ErrorOr open(BAN::StringView, int); BAN::ErrorOr close(int fd); - BAN::ErrorOr read(int fd, void* buffer, size_t offset, size_t count); - BAN::ErrorOr write(int fd, const void* buffer, size_t offset, size_t count); + BAN::ErrorOr read(int fd, void* buffer, size_t count); + BAN::ErrorOr write(int fd, const void* buffer, size_t count); BAN::ErrorOr creat(BAN::StringView name, mode_t); + BAN::ErrorOr seek(int fd, off_t offset, int whence); + BAN::ErrorOr tell(int fd); + BAN::ErrorOr fstat(int fd, struct stat*); BAN::ErrorOr stat(BAN::StringView path, struct stat*); @@ -77,7 +80,8 @@ namespace Kernel { BAN::RefPtr inode; BAN::String path; - uint8_t flags = 0; + off_t offset { 0 }; + uint8_t flags { 0 }; }; BAN::ErrorOr validate_fd(int); diff --git a/kernel/include/kernel/Syscall.h b/kernel/include/kernel/Syscall.h index a3e52e14..c3792c5d 100644 --- a/kernel/include/kernel/Syscall.h +++ b/kernel/include/kernel/Syscall.h @@ -8,6 +8,8 @@ #define SYS_OPEN 6 #define SYS_ALLOC 7 #define SYS_FREE 8 +#define SYS_SEEK 9 +#define SYS_TELL 10 #include #include diff --git a/kernel/kernel/Font.cpp b/kernel/kernel/Font.cpp index 3bd31da8..ed5b897a 100644 --- a/kernel/kernel/Font.cpp +++ b/kernel/kernel/Font.cpp @@ -45,7 +45,7 @@ namespace Kernel BAN::Vector file_data; TRY(file_data.resize(st.st_size)); - TRY(Process::current().read(fd, file_data.data(), 0, st.st_size)); + TRY(Process::current().read(fd, file_data.data(), st.st_size)); if (file_data.size() < 4) return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index fa197fa5..e0542ba2 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace Kernel { @@ -210,6 +211,7 @@ namespace Kernel auto& open_file_description = m_open_files[fd]; open_file_description.inode = file.inode; open_file_description.path = BAN::move(file.canonical_path); + open_file_description.offset = 0; open_file_description.flags = flags; return fd; @@ -224,7 +226,7 @@ namespace Kernel return {}; } - BAN::ErrorOr Process::read(int fd, void* buffer, size_t offset, size_t count) + BAN::ErrorOr Process::read(int fd, void* buffer, size_t count) { OpenFileDescription open_fd_copy; @@ -236,10 +238,19 @@ namespace Kernel if (!(open_fd_copy.flags & O_RDONLY)) return BAN::Error::from_errno(EBADF); - return TRY(open_fd_copy.inode->read(offset, buffer, count)); + + size_t nread = TRY(open_fd_copy.inode->read(open_fd_copy.offset, buffer, count)); + + { + LockGuard _(m_lock); + MUST(validate_fd(fd)); + open_file_description(fd).offset += nread; + } + + return nread; } - BAN::ErrorOr Process::write(int fd, const void* buffer, size_t offset, size_t count) + BAN::ErrorOr Process::write(int fd, const void* buffer, size_t count) { OpenFileDescription open_fd_copy; @@ -251,7 +262,54 @@ namespace Kernel if (!(open_fd_copy.flags & O_WRONLY)) return BAN::Error::from_errno(EBADF); - return TRY(open_fd_copy.inode->write(offset, buffer, count)); + + size_t nwrite = TRY(open_fd_copy.inode->write(open_fd_copy.offset, buffer, count)); + + { + LockGuard _(m_lock); + MUST(validate_fd(fd)); + open_file_description(fd).offset += nwrite; + } + + return nwrite; + } + + BAN::ErrorOr Process::seek(int fd, off_t offset, int whence) + { + LockGuard _(m_lock); + TRY(validate_fd(fd)); + + auto& open_fd = open_file_description(fd); + + off_t new_offset = 0; + + switch (whence) + { + case SEEK_CUR: + new_offset = open_fd.offset + offset; + break; + case SEEK_END: + new_offset = open_fd.inode->size() - offset; + break; + case SEEK_SET: + new_offset = offset; + break; + default: + return BAN::Error::from_errno(EINVAL); + } + + if (new_offset < 0) + return BAN::Error::from_errno(EINVAL); + open_fd.offset = new_offset; + + return {}; + } + + BAN::ErrorOr Process::tell(int fd) + { + LockGuard _(m_lock); + TRY(validate_fd(fd)); + return open_file_description(fd).offset; } BAN::ErrorOr Process::creat(BAN::StringView path, mode_t mode) diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index e8c41465..afae7316 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -22,14 +22,14 @@ namespace Kernel static void TTY_PRINT(Args&&... args) { BAN::String message = BAN::String::formatted(BAN::forward(args)...); - MUST(Process::current().write(STDOUT_FILENO, message.data(), 0, message.size())); + MUST(Process::current().write(STDOUT_FILENO, message.data(), message.size())); } template static void TTY_PRINTLN(Args&&... args) { TTY_PRINT(BAN::forward(args)...); - MUST(Process::current().write(STDOUT_FILENO, "\n", 0, 1)); + MUST(Process::current().write(STDOUT_FILENO, "\n", 1)); } 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() { - auto getch = [this] { uint8_t ch; MUST(Process::current().read(STDIN_FILENO, &ch, 0, 1)); return ch; }; + auto getch = [this] { uint8_t ch; MUST(Process::current().read(STDIN_FILENO, &ch, 1)); return ch; }; MUST(m_buffer.push_back(""sv)); @@ -130,7 +130,7 @@ namespace Kernel while ((current.back() & 0xC0) == 0x80) current.pop_back(); current.pop_back(); - MUST(Process::current().write(STDOUT_FILENO, "\b \b", 0, 3)); + MUST(Process::current().write(STDOUT_FILENO, "\b \b", 3)); } continue; } @@ -171,7 +171,7 @@ namespace Kernel continue; } - MUST(Process::current().write(STDOUT_FILENO, &ch, 0, 1)); + MUST(Process::current().write(STDOUT_FILENO, &ch, 1)); if (ch != '\n') { @@ -556,12 +556,8 @@ argument_done: BAN::ScopeGuard buffer_guard([buffer] { delete[] buffer; }); ASSERT(buffer); - size_t offset = 0; - while (size_t n_read = TRY(Process::current().read(fd, buffer, offset, buffer_size))) - { + while (size_t n_read = TRY(Process::current().read(fd, buffer, buffer_size))) TTY_PRINT("{}", BAN::StringView(buffer, n_read)); - offset += n_read; - } TTY_PRINTLN(""); } else if (arguments.front() == "stat") @@ -639,7 +635,7 @@ argument_done: while (true) { - size_t n_read = TRY(Process::current().read(fd, buffer, total_read, buffer_size)); + size_t n_read = TRY(Process::current().read(fd, buffer, buffer_size)); if (n_read == 0) break; for (size_t j = 0; j < n_read; j++) diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 160058ed..5c7e106f 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -10,17 +10,17 @@ namespace Kernel Process::current().exit(); } - long sys_read(int fd, void* buffer, size_t offset, size_t size) + long sys_read(int fd, void* buffer, size_t size) { - auto res = Process::current().read(fd, buffer, offset, size); + auto res = Process::current().read(fd, buffer, size); if (res.is_error()) return -res.error().get_error_code(); return res.value(); } - long sys_write(int fd, const void* buffer, size_t offset, size_t size) + long sys_write(int fd, const void* buffer, size_t size) { - auto res = Process::current().write(fd, buffer, offset, size); + auto res = Process::current().write(fd, buffer, size); if (res.is_error()) return -res.error().get_error_code(); return res.value(); @@ -60,12 +60,32 @@ namespace Kernel Process::current().free(ptr); } + long sys_seek(int fd, long offset, int whence) + { + auto res = Process::current().seek(fd, offset, whence); + if (res.is_error()) + return -res.error().get_error_code(); + return 0; + } + + long sys_tell(int fd) + { + auto res = Process::current().tell(fd); + if (res.is_error()) + return -res.error().get_error_code(); + return res.value(); + } + 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); asm volatile("sti"); + (void)arg1; + (void)arg2; + (void)arg3; + (void)arg4; (void)arg5; long ret = 0; @@ -75,10 +95,10 @@ namespace Kernel sys_exit(); break; case SYS_READ: - ret = sys_read((int)arg1, (void*)arg2, (size_t)arg3, (size_t)arg4); + ret = sys_read((int)arg1, (void*)arg2, (size_t)arg3); break; case SYS_WRITE: - ret = sys_write((int)arg1, (const void*)arg2, (size_t)arg3, (size_t)arg4); + ret = sys_write((int)arg1, (const void*)arg2, (size_t)arg3); break; case SYS_TERMID: sys_termid((char*)arg1); @@ -95,6 +115,12 @@ namespace Kernel case SYS_FREE: sys_free((void*)arg1); break; + case SYS_SEEK: + ret = sys_seek((int)arg1, (long)arg2, (int)arg3); + break; + case SYS_TELL: + ret = sys_tell((int)arg1); + break; default: Kernel::panic("Unknown syscall {}", syscall); } diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 85a4b7ba..e99c67bb 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -66,7 +66,7 @@ namespace Kernel while (true) { Input::KeyEvent event; - ASSERT(MUST(Process::current().read(fd, &event, 0, sizeof(event))) == sizeof(event)); + ASSERT(MUST(Process::current().read(fd, &event, sizeof(event))) == sizeof(event)); TTY::current()->on_key(event); } }, nullptr diff --git a/libc/stdio.cpp b/libc/stdio.cpp index a425ec43..eecfe8e8 100644 --- a/libc/stdio.cpp +++ b/libc/stdio.cpp @@ -10,7 +10,6 @@ struct FILE { int fd { -1 }; - off_t offset { 0 }; bool eof { false }; bool error { false }; @@ -77,7 +76,7 @@ int fflush(FILE* file) if (file->buffer_index == 0) return 0; - if (syscall(SYS_WRITE, file->fd, file->buffer, file->offset, file->buffer_index) < 0) + if (syscall(SYS_WRITE, file->fd, file->buffer, file->buffer_index) < 0) { file->error = true; return EOF; @@ -93,7 +92,7 @@ int fgetc(FILE* file) return EOF; unsigned char c; - long ret = syscall(SYS_READ, file->fd, &c, file->offset, 1); + long ret = syscall(SYS_READ, file->fd, &c, 1); if (ret < 0) { @@ -107,13 +106,15 @@ int fgetc(FILE* file) return EOF; } - file->offset++; return c; } int fgetpos(FILE* file, fpos_t* pos) { - *pos = file->offset; + off_t offset = ftello(file); + if (offset == -1) + return -1; + *pos = offset; return 0; } @@ -214,7 +215,6 @@ int fprintf(FILE* file, const char* format, ...) int fputc(int c, FILE* file) { file->buffer[file->buffer_index++] = c; - file->offset++; if (c == '\n' || file->buffer_index == sizeof(file->buffer)) if (fflush(file) == EOF) return EOF; @@ -236,15 +236,14 @@ size_t fread(void* buffer, size_t size, size_t nitems, FILE* file) { if (file->eof || nitems * size == 0) return 0; - long ret = syscall(SYS_READ, file->fd, buffer, file->offset, size * nitems); + long ret = syscall(SYS_READ, file->fd, buffer, size * nitems); if (ret < 0) { file->error = true; return 0; } - if (ret < size * nitems) + if (ret == 0) file->eof = true; - file->offset += ret; return ret / size; } @@ -261,29 +260,11 @@ int fseek(FILE* file, long offset, int whence) int fseeko(FILE* file, off_t offset, int whence) { - if (offset < 0) - { - errno = EINVAL; + long ret = syscall(SYS_SEEK, file->fd, offset, whence); + if (ret < 0) return -1; - } - - if (whence == SEEK_CUR && offset <= file->offset) - file->offset += offset; - else if (whence == SEEK_SET) - file->offset = offset; - else if (whence == SEEK_END) - { - errno = ENOTSUP; - return -1; - } - else - { - errno = EINVAL; - return -1; - } - + file->eof = false; - return 0; } @@ -299,7 +280,10 @@ long ftell(FILE* file) off_t ftello(FILE* file) { - return file->offset; + long ret = syscall(SYS_TELL, file->fd); + if (ret < 0) + return -1; + return ret; } // TODO diff --git a/libc/unistd.cpp b/libc/unistd.cpp index 19ecdc2a..49104e1d 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -76,6 +76,20 @@ long syscall(long syscall, ...) ret = Kernel::syscall(SYS_FREE, (uintptr_t)ptr); break; } + case SYS_SEEK: + { + int fd = va_arg(args, int); + off_t offset = va_arg(args, off_t); + int whence = va_arg(args, int); + ret = Kernel::syscall(SYS_SEEK, fd, offset, whence); + break; + } + case SYS_TELL: + { + int fd = va_arg(args, int); + ret = Kernel::syscall(SYS_TELL, fd); + break; + } default: puts("LibC: Unhandeled syscall"); ret = -ENOSYS;