summaryrefslogtreecommitdiff
path: root/src/user/lib/stdlib.c
diff options
context:
space:
mode:
authordzwdz2022-07-26 22:04:19 +0200
committerdzwdz2022-07-26 22:04:19 +0200
commit137dcb3e207b264c467f4b2b13df2316b8b0a67c (patch)
tree29f01a9c4eca62ec6b0f443d8a48eeda563df452 /src/user/lib/stdlib.c
parent4d19346cf0d2a93eed9afe22e5c2a5d9a30fb37c (diff)
user/libc: fread, fwrite, fclose
Diffstat (limited to 'src/user/lib/stdlib.c')
-rw-r--r--src/user/lib/stdlib.c85
1 files changed, 63 insertions, 22 deletions
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;
}