diff options
author | dzwdz | 2022-08-05 19:54:22 +0200 |
---|---|---|
committer | dzwdz | 2022-08-05 19:54:22 +0200 |
commit | 4fcff0ecc6f94dbc079f29b9636d810a16ef2ed7 (patch) | |
tree | 1ae354131b7bffd2b3f7a671f78cd31371b261c8 /src/user/lib/file.c | |
parent | 99e15199ef24d4f262683b47a529f1b239c4dcd9 (diff) |
user/libc: fseek + ftell for getting a file's size
Diffstat (limited to 'src/user/lib/file.c')
-rw-r--r-- | src/user/lib/file.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/src/user/lib/file.c b/src/user/lib/file.c index 84242b2..942b522 100644 --- a/src/user/lib/file.c +++ b/src/user/lib/file.c @@ -175,31 +175,44 @@ int fseek(FILE *f, long offset, int whence) { if (fflush(f)) return -1; + long base; switch (whence) { case SEEK_SET: - f->pos = 0; + base = 0; break; case SEEK_CUR: + base = f->pos; break; case SEEK_END: - f->pos = -1; + base = _syscall_getsize(f->fd); + if (base < 0) + base = -1; break; default: errno = EINVAL; return -1; } - bool pos_neg = f->pos < 0; - f->pos += offset; - if (pos_neg && f->pos >= 0) { - // TODO getting the file size - errno = ENOSYS; + if (base >= 0 && base + offset < 0) { + /* underflow */ + errno = EINVAL; + return -1; + } else if (base < 0 && base + offset >= 0) { + /* overflow - went from a negative offset (relative to EOF) + * to a positive offset (from start of file). + * can only happen when getsize() is unsupported */ + errno = EINVAL; return -1; } + f->pos = base + offset; f->eof = false; return 0; } +long ftell(FILE *f) { + return f->pos; +} + int fclose(FILE *f) { fflush(f); if (f->fd > 0) close(f->fd); |