summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordzwdz2022-07-26 22:04:19 +0200
committerdzwdz2022-07-26 22:04:19 +0200
commit137dcb3e207b264c467f4b2b13df2316b8b0a67c (patch)
tree29f01a9c4eca62ec6b0f443d8a48eeda563df452 /src
parent4d19346cf0d2a93eed9afe22e5c2a5d9a30fb37c (diff)
user/libc: fread, fwrite, fclose
Diffstat (limited to 'src')
-rw-r--r--src/shared/include/camellia/errno.h1
-rw-r--r--src/user/app/init/shell.c10
-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
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;
}