diff options
author | Anton Kling <anton@kling.gg> | 2024-06-22 21:41:46 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-06-22 21:41:46 +0200 |
commit | 5fbd9b519e082fc235a8a57c6cf761e6cefbfb62 (patch) | |
tree | d9df62f8bf6ed6b17a7b61aa77f61da9d097c5ff /userland | |
parent | 5e10cdd5b4aa7486208dd14ebef4254ec5b5d03a (diff) |
LibC: Fix bugs relating to fseek
Diffstat (limited to 'userland')
-rw-r--r-- | userland/libc/stdio/fgetc.c | 1 | ||||
-rw-r--r-- | userland/libc/stdio/fseek.c | 21 | ||||
-rw-r--r-- | userland/libc/stdio/ftell.c | 2 | ||||
-rw-r--r-- | userland/libc/stdio/stdin.c | 3 | ||||
-rw-r--r-- | userland/libc/stdio/ungetc.c | 1 | ||||
-rw-r--r-- | userland/libc/string/sscanf.c | 36 |
6 files changed, 41 insertions, 23 deletions
diff --git a/userland/libc/stdio/fgetc.c b/userland/libc/stdio/fgetc.c index c69211f..afa299f 100644 --- a/userland/libc/stdio/fgetc.c +++ b/userland/libc/stdio/fgetc.c @@ -4,6 +4,7 @@ int fgetc(FILE *stream) { if (stream->has_buffered_char) { stream->has_buffered_char = 0; + fseek(stream, 1, SEEK_CUR); return stream->buffered_char; } char c; diff --git a/userland/libc/stdio/fseek.c b/userland/libc/stdio/fseek.c index fb891ec..cbccbb8 100644 --- a/userland/libc/stdio/fseek.c +++ b/userland/libc/stdio/fseek.c @@ -1,21 +1,8 @@ -#include <stdio.h> #include <assert.h> +#include <stdio.h> int fseek(FILE *stream, long offset, int whence) { - return stream->seek(stream, offset, whence); - /* - switch (whence) { - case SEEK_SET: - stream->offset_in_file = offset; - break; - case SEEK_CUR: - stream->offset_in_file += offset; - break; - case SEEK_END: - // FIXME - assert(0); - break; - } - // FIXME: Error checking - return 0;*/ + stream->read_buffer_stored = 0; + assert(stream->seek); + return stream->seek(stream, offset, whence); } diff --git a/userland/libc/stdio/ftell.c b/userland/libc/stdio/ftell.c index 35076d0..1729d74 100644 --- a/userland/libc/stdio/ftell.c +++ b/userland/libc/stdio/ftell.c @@ -1,5 +1,5 @@ #include <stdio.h> long ftell(FILE *stream) { - return stream->offset_in_file; + return fseek(stream, 0, SEEK_CUR); } diff --git a/userland/libc/stdio/stdin.c b/userland/libc/stdio/stdin.c index fcfc71e..e497167 100644 --- a/userland/libc/stdio/stdin.c +++ b/userland/libc/stdio/stdin.c @@ -71,10 +71,13 @@ size_t read_fd(FILE *f, unsigned char *s, size_t l) { f->read_buffer_has_read += read_len; s += read_len; l -= read_len; + lseek(f->fd, read_len, SEEK_CUR); return read_len + read_fd(f, s, l); } if (0 == f->read_buffer_stored) { + int offset = lseek(f->fd, 0, SEEK_CUR); f->read_buffer_stored = non_cache_read_fd(f, f->read_buffer, 4096); + lseek(f->fd, offset, SEEK_SET); f->read_buffer_has_read = 0; if (0 == f->read_buffer_stored) { return 0; diff --git a/userland/libc/stdio/ungetc.c b/userland/libc/stdio/ungetc.c index 8d649bc..3b93b70 100644 --- a/userland/libc/stdio/ungetc.c +++ b/userland/libc/stdio/ungetc.c @@ -5,5 +5,6 @@ int ungetc(int c, FILE *stream) { return EOF; stream->buffered_char = c; stream->has_buffered_char = 1; + fseek(stream, -1, SEEK_CUR); return c; } diff --git a/userland/libc/string/sscanf.c b/userland/libc/string/sscanf.c index 28e1ce1..e1ede63 100644 --- a/userland/libc/string/sscanf.c +++ b/userland/libc/string/sscanf.c @@ -150,20 +150,21 @@ int vfscanf(FILE *stream, const char *format, va_list ap) { struct sscanf_cookie { const char *s; + unsigned long offset; }; size_t sscanf_read(FILE *f, unsigned char *s, size_t l) { struct sscanf_cookie *c = f->cookie; - if (!*(c->s)) { + if (!*(c->s + c->offset)) { return 0; } size_t r = 0; - for (; l && *(c->s); l--, c->s += 1) { - *s = *(c->s); + for (; l && *(c->s); l--, c->offset += 1) { + *s = *(c->s + c->offset); s++; r++; } - if (!(*(c->s))) + if (!(*(c->s + c->offset))) f->is_eof = 1; /* memcpy(s, c->s, l); @@ -171,10 +172,35 @@ size_t sscanf_read(FILE *f, unsigned char *s, size_t l) { return r; } +int sscanf_seek(FILE *stream, long offset, int whence) { + struct sscanf_cookie *c = stream->cookie; + off_t ret_offset = c->offset; + switch (whence) { + case SEEK_SET: + // TODO: Avoid running past the pointer + // Should that even be checked? + ret_offset = offset; + break; + case SEEK_CUR: + ret_offset += offset; + break; + case SEEK_END: + for (; *(c->s + ret_offset); ret_offset++) + ; + break; + default: + return -EINVAL; + break; + } + c->offset = ret_offset; + return ret_offset; +} + int vsscanf(const char *s, const char *restrict format, va_list ap) { - struct sscanf_cookie c = {.s = s}; + struct sscanf_cookie c = {.s = s, .offset = 0}; FILE f = { .read = sscanf_read, + .seek = sscanf_seek, .cookie = &c, .has_buffered_char = 0, .is_eof = 0, |