diff options
author | dzwdz | 2022-07-26 22:04:19 +0200 |
---|---|---|
committer | dzwdz | 2022-07-26 22:04:19 +0200 |
commit | 137dcb3e207b264c467f4b2b13df2316b8b0a67c (patch) | |
tree | 29f01a9c4eca62ec6b0f443d8a48eeda563df452 /src | |
parent | 4d19346cf0d2a93eed9afe22e5c2a5d9a30fb37c (diff) |
user/libc: fread, fwrite, fclose
Diffstat (limited to 'src')
-rw-r--r-- | src/shared/include/camellia/errno.h | 1 | ||||
-rw-r--r-- | src/user/app/init/shell.c | 10 | ||||
-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 |
6 files changed, 79 insertions, 42 deletions
diff --git a/src/shared/include/camellia/errno.h b/src/shared/include/camellia/errno.h index a0b5731..a269fa3 100644 --- a/src/shared/include/camellia/errno.h +++ b/src/shared/include/camellia/errno.h @@ -1,3 +1,4 @@ #pragma once #define EFAULT 2 +#define EBADF 3 /* Invalid file descriptor. */ diff --git a/src/user/app/init/shell.c b/src/user/app/init/shell.c index 795bb5e..253acce 100644 --- a/src/user/app/init/shell.c +++ b/src/user/app/init/shell.c @@ -38,7 +38,7 @@ static char *strtrim(char *s) { static int readline(char *buf, size_t max) { char c = '\0'; size_t pos = 0; - while (pos < (max-1) && c != '\n' && file_read(stdin, &c, 1)) + while (pos < (max-1) && c != '\n' && fread(&c, 1, 1, stdin)) buf[pos++] = c; buf[pos++] = '\0'; return pos; @@ -73,16 +73,16 @@ static void cmd_cat_ls(const char *args, bool ls) { } while (!file->eof) { - int len = file_read(file, buf, sizeof buf); + int len = fread(buf, 1, sizeof buf, file); if (len <= 0) break; if (ls) { for (int i = 0; i < len; i++) if (buf[i] == '\0') buf[i] = '\n'; } - file_write(stdout, buf, len); + fwrite(buf, 1, len, stdout); } - file_close(file); + fclose(file); } static void cmd_hexdump(const char *args) { @@ -166,7 +166,7 @@ void shell_loop(void) { printf("couldn't open file\n"); } else { elf_execf(file); - file_close(file); + fclose(file); printf("elf_execf failed\n"); } } else if (!strcmp(cmd, "cat")) { 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; } |