diff options
Diffstat (limited to 'src/user')
-rw-r--r-- | src/user/app/vterm/font.c | 17 | ||||
-rw-r--r-- | src/user/lib/elfload.c | 14 | ||||
-rw-r--r-- | src/user/lib/file.c | 27 | ||||
-rw-r--r-- | src/user/lib/include/stdio.h | 1 |
4 files changed, 45 insertions, 14 deletions
diff --git a/src/user/app/vterm/font.c b/src/user/app/vterm/font.c index d9a4e3c..5a9dd24 100644 --- a/src/user/app/vterm/font.c +++ b/src/user/app/vterm/font.c @@ -13,13 +13,24 @@ void font_load(const char *path) { exit(1); } - const size_t cap = 8 * 1024; // TODO get file size - void *buf = malloc(cap); + void *buf; + long buflen; + + fseek(f, 0, SEEK_END); + buflen = ftell(f); + if (buflen < 0) { + eprintf("can't get the size of \"%s\"", path); + exit(1); + } + + buf = malloc(buflen); if (!buf) { eprintf("out of memory"); exit(1); } - fread(buf, 1, cap, f); + + fseek(f, 0, SEEK_SET); + fread(buf, 1, buflen, f); if (ferror(f)) { eprintf("error reading file"); exit(1); diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index e3853ba..7c84f45 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -9,11 +9,17 @@ #include <user/lib/elfload.h> void elf_execf(FILE *f, char **argv, char **envp) { - const size_t cap = 0x60000; - size_t pos = 0; - void *buf = malloc(cap); // TODO a way to get file size + void *buf; + long buflen; - if (buf && fread(buf, 1, cap - pos, f)) + fseek(f, 0, SEEK_END); + buflen = ftell(f); + if (buflen < 0) return; /* errno set by fseek */ + buf = malloc(buflen); + + // TODO don't read the entire file into memory + fseek(f, 0, SEEK_SET); + if (buf && fread(buf, 1, buflen, f)) elf_exec(buf, argv, envp); free(buf); } 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); diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h index 74c5230..063c81f 100644 --- a/src/user/lib/include/stdio.h +++ b/src/user/lib/include/stdio.h @@ -33,6 +33,7 @@ size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict); size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict); char *fgets(char *buf, int size, FILE *f); int fseek(FILE *f, long offset, int whence); +long ftell(FILE *f); int feof(FILE *); int ferror(FILE *); |