diff options
Diffstat (limited to 'src/user/lib')
-rw-r--r-- | src/user/lib/elfload.c | 12 | ||||
-rw-r--r-- | src/user/lib/include/bits/file.h | 1 | ||||
-rw-r--r-- | src/user/lib/include/stdio.h | 12 | ||||
-rw-r--r-- | src/user/lib/stdlib.c | 85 |
4 files changed, 73 insertions, 37 deletions
diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index 75c1162..b73dfe5 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -11,17 +11,9 @@ void elf_execf(FILE *f) { const size_t cap = 0x60000; size_t pos = 0; void *buf = malloc(cap); // TODO a way to get file size - if (!buf) goto fail; + if (buf && fread(buf, 1, cap - pos, f)) + elf_exec(buf); - while (!f->eof) { - long ret = file_read(f, buf, cap - pos); - if (ret < 0) goto fail; - pos += ret; - if (pos >= cap) goto fail; - } - elf_exec(buf); - -fail: free(buf); } diff --git a/src/user/lib/include/bits/file.h b/src/user/lib/include/bits/file.h index 74a8c17..e50d402 100644 --- a/src/user/lib/include/bits/file.h +++ b/src/user/lib/include/bits/file.h @@ -5,5 +5,6 @@ struct FILE { int fd; int pos; bool eof; + bool error; }; typedef struct FILE FILE; diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h index 9d6921a..2f0746f 100644 --- a/src/user/lib/include/stdio.h +++ b/src/user/lib/include/stdio.h @@ -2,6 +2,8 @@ #include <bits/file.h> #include <stddef.h> +#define EOF (-1) + int printf(const char *fmt, ...); int snprintf(char *str, size_t len, const char *fmt, ...); @@ -11,9 +13,9 @@ int _klogf(const char *fmt, ...); // for kernel debugging only extern FILE *const stdin, *const stdout; FILE *fopen(const char *path, const char *mode); -FILE *freopen(const char *path, const char *mode, FILE*); +FILE *freopen(const char *path, const char *mode, FILE *); FILE *fdopen(int fd, const char *mode); -FILE *file_clone(const FILE*); -int file_read(FILE*, char *buf, size_t len); -int file_write(FILE*, const char *buf, size_t len); -void file_close(FILE*); +FILE *file_clone(const FILE *); +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); +int fclose(FILE *); diff --git a/src/user/lib/stdlib.c b/src/user/lib/stdlib.c index 0eb145f..cd2ec90 100644 --- a/src/user/lib/stdlib.c +++ b/src/user/lib/stdlib.c @@ -15,7 +15,7 @@ FILE *const stdin = &_stdin_null, *const stdout = &_stdout_null; int errno = 0; static void backend_file(void *arg, const char *buf, size_t len) { - file_write((FILE*)arg, buf, len); + fwrite(buf, 1, len, (FILE *)arg); } int printf(const char *fmt, ...) { @@ -93,13 +93,13 @@ FILE *fopen(const char *path, const char *mode) { } f->pos = f2->pos; f->eof = f2->eof; - file_close(f2); + fclose(f2); return f; fail2: - file_close(f2); + fclose(f2); fail: - file_close(f); + fclose(f); return NULL; } @@ -110,6 +110,7 @@ FILE *fdopen(int fd, const char *mode) { f->pos = mode[0] == 'a' ? -1 : 0; f->eof = false; f->fd = fd; + f->error = false; return f; } @@ -129,34 +130,74 @@ FILE *file_clone(const FILE *f) { return f2; } -int file_read(FILE *f, char *buf, size_t len) { - if (f->fd < 0) return -1; - - int res = _syscall_read(f->fd, buf, len, f->pos); - if (res < 0) return res; - if (res == 0 && len > 0) f->eof = true; - - bool negative_pos = f->pos < 0; - f->pos += res; - if (negative_pos && f->pos >= 0) +static void fadvance(long amt, FILE *f) { + bool pos_neg = f->pos < 0; + f->pos += amt; + if (pos_neg && f->pos >= 0) f->pos = -1; +} + +size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict f) { + size_t total = size*nitems, pos = 0; + unsigned char *buf = ptr; - return res; + if (f->fd < 0) { + errno = EBADF; + return 0; + } + if (size == 0) + return 0; + + while (pos < total) { + long res = _syscall_read(f->fd, buf + pos, total - pos, f->pos); + if (res < 0) { + f->error = true; + errno = -res; + return pos/size; + } else if (res == 0) { + f->eof = true; + return pos/size; + } else { + pos += res; + fadvance(res, f); + } + } + return nitems; } -int file_write(FILE *f, const char *buf, size_t len) { - if (f->fd < 0) return -1; +size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict f) { + size_t total = size*nitems, pos = 0; + const unsigned char *buf = ptr; - int res = _syscall_write(f->fd, buf, len, f->pos); - if (res < 0) return res; - f->pos += res; - return res; + if (f->fd < 0) { + errno = EBADF; + return 0; + } + if (size == 0) + return 0; + + while (pos < total) { + long res = _syscall_write(f->fd, buf + pos, total - pos, f->pos); + if (res < 0) { + f->error = true; + errno = -res; + return pos/size; + } else if (res == 0) { + f->eof = true; + return pos/size; + } else { + pos += res; + fadvance(res, f); + } + } + return nitems; } -void file_close(FILE *f) { +int fclose(FILE *f) { if (f->fd > 0) close(f->fd); if (f != &_stdin_null && f != &_stdout_null) free(f); + return 0; } |