summaryrefslogtreecommitdiff
path: root/src/user/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/lib')
-rw-r--r--src/user/lib/elfload.c12
-rw-r--r--src/user/lib/include/bits/file.h1
-rw-r--r--src/user/lib/include/stdio.h12
-rw-r--r--src/user/lib/stdlib.c85
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;
}