From edda41a7bb9548e83cb995c9c2e1ffb4bb37faf1 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 12 Oct 2022 15:56:03 +0200 Subject: [PATCH] libc: Implement fseek(), ftell() and rewind() All three use the new syscall seek() (with its lseek() wrapper in unistd.h)!! --- apps/src/init.c | 17 +++++++++++++++++ kernel/src/fs/FileDescriptor.cpp | 3 ++- kernel/src/sys/Syscall.cpp | 2 +- libs/libc/include/stdio.h | 10 ++++++++-- libs/libc/include/sys/mman.h | 3 +-- libs/libc/src/file.cpp | 18 ++++++++++++++---- 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/apps/src/init.c b/apps/src/init.c index 732110a1..9360023f 100644 --- a/apps/src/init.c +++ b/apps/src/init.c @@ -85,6 +85,23 @@ int main() return 1; } + if (fseek(config, 0, SEEK_END) < 0) + { + perror("fseek"); + return 1; + } + + long offset = ftell(config); + if (offset < 0) + { + perror("ftell"); + return 1; + } + + printf("%s is %ld bytes long\n", filename, offset); + + rewind(config); + char buf[4096]; size_t nread = fread(buf, sizeof(buf), 1, config); diff --git a/kernel/src/fs/FileDescriptor.cpp b/kernel/src/fs/FileDescriptor.cpp index 2cf2b27d..d45d41b6 100644 --- a/kernel/src/fs/FileDescriptor.cpp +++ b/kernel/src/fs/FileDescriptor.cpp @@ -36,7 +36,8 @@ ssize_t Descriptor::write(size_t size, const char* buffer) int Descriptor::seek(long offset) { - if (m_node->type != VFS_DEVICE && offset > m_node->length) + if (m_node->type != VFS_DEVICE && (uint64_t)offset > m_node->length) return -EINVAL; // FIXME: Support seeking beyond the current file's length. m_offset = (uint64_t)offset; + return 0; } \ No newline at end of file diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp index 62469182..14c79802 100644 --- a/kernel/src/sys/Syscall.cpp +++ b/kernel/src/sys/Syscall.cpp @@ -20,7 +20,7 @@ void Syscall::entry(Context* context) case SYS_open: sys_open(context, (const char*)context->rdi, (int)context->rsi); break; case SYS_read: sys_read(context, (int)context->rdi, context->rsi, (char*)context->rdx); break; case SYS_close: sys_close(context, (int)context->rdi); break; - case SYS_seek: sys_seek(context, (int)context->rdi, (long)context->rsi, (int)context->rdx); + case SYS_seek: sys_seek(context, (int)context->rdi, (long)context->rsi, (int)context->rdx); break; default: context->rax = -ENOSYS; break; } } \ No newline at end of file diff --git a/libs/libc/include/stdio.h b/libs/libc/include/stdio.h index 37303dd3..0173caac 100644 --- a/libs/libc/include/stdio.h +++ b/libs/libc/include/stdio.h @@ -38,8 +38,14 @@ extern "C" /* Reads nmemb items of size size from the file stream into buf. */ size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream); - int fseek(FILE*, long, int); // Not implemented. - long ftell(FILE*); // Not implemented. + /* Moves stream's read/write offset by offset, depending on whence. */ + int fseek(FILE* stream, long offset, int whence); + + /* Returns the current offset for stream. */ + long ftell(FILE* stream); + + /* Rewinds stream's offset to start of file. */ + void rewind(FILE* stream); /* Writes nmemb items of size size from buf into the file stream. */ size_t fwrite(const void* buf, size_t size, size_t nmemb, FILE* stream); diff --git a/libs/libc/include/sys/mman.h b/libs/libc/include/sys/mman.h index bcee7711..fbb6d3c5 100644 --- a/libs/libc/include/sys/mman.h +++ b/libs/libc/include/sys/mman.h @@ -2,8 +2,7 @@ #define _SYS_MMAN_H #include - -typedef unsigned long off_t; +#include // for off_t /* Address returned by mmap when it fails. */ #define MAP_FAILED (void*)-1 diff --git a/libs/libc/src/file.cpp b/libs/libc/src/file.cpp index 8e70e47a..2aade1dd 100644 --- a/libs/libc/src/file.cpp +++ b/libs/libc/src/file.cpp @@ -67,14 +67,24 @@ extern "C" stream->f_err = stream->f_eof = 0; } - int fseek(FILE*, long, int) + int fseek(FILE* stream, long offset, int whence) { - NOT_IMPLEMENTED("fseek"); + long result = lseek(stream->f_fd, offset, whence); + if (result < 0) { return -1; } + return 0; } - long ftell(FILE*) + long ftell(FILE* stream) { - NOT_IMPLEMENTED("ftell"); + return lseek(stream->f_fd, 0, + SEEK_CUR); // FIXME: Store the last seeked position in the file struct to avoid redundant syscalls + // maybe? We'd have to update this value in fread() and fwrite() as well... + } + + void rewind(FILE* stream) + { + lseek(stream->f_fd, 0, SEEK_SET); + clearerr(stream); } size_t fwrite(const void* buf, size_t size, size_t nmemb, FILE* stream)