From 4d19346cf0d2a93eed9afe22e5c2a5d9a30fb37c Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Tue, 26 Jul 2022 20:51:33 +0200
Subject: user/libc: fdopen

---
 src/user/lib/include/stdio.h |  1 +
 src/user/lib/stdlib.c        | 32 ++++++++++++++++++--------------
 2 files changed, 19 insertions(+), 14 deletions(-)

(limited to 'src/user')

diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h
index 2b1d8ed..9d6921a 100644
--- a/src/user/lib/include/stdio.h
+++ b/src/user/lib/include/stdio.h
@@ -12,6 +12,7 @@ extern FILE *const stdin, *const stdout;
 
 FILE *fopen(const char *path, const char *mode);
 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);
diff --git a/src/user/lib/stdlib.c b/src/user/lib/stdlib.c
index af653bb..0eb145f 100644
--- a/src/user/lib/stdlib.c
+++ b/src/user/lib/stdlib.c
@@ -74,15 +74,8 @@ FILE *fopen(const char *path, const char *mode) {
 		errno = -h;
 		return NULL;
 	}
-
-	f = malloc(sizeof *f);
-	if (!f) {
-		close(h);
-		return NULL;
-	}
-	f->pos = mode[0] == 'a' ? -1 : 0;
-	f->eof = false;
-	f->fd = h;
+	f = fdopen(h, mode);
+	if (!f) close(h);
 	return f;
 }
 
@@ -93,9 +86,11 @@ FILE *fopen(const char *path, const char *mode) {
 	f2 = fopen(path, mode);
 	if (!f2) goto fail;
 
-	if (f->fd == f2->fd) f2->fd = -1;
-
-	if (_syscall_dup(f2->fd, f->fd, 0) < 0) goto fail2;
+	if (f->fd == f2->fd) {
+		f2->fd = -1;
+	} else {
+		if (_syscall_dup(f2->fd, f->fd, 0) < 0) goto fail2;
+	}
 	f->pos = f2->pos;
 	f->eof = f2->eof;
 	file_close(f2);
@@ -108,13 +103,22 @@ fail:
 	return NULL;
 }
 
+FILE *fdopen(int fd, const char *mode) {
+	FILE *f;
+	f = malloc(sizeof *f);
+	if (!f) return NULL;
+	f->pos = mode[0] == 'a' ? -1 : 0;
+	f->eof = false;
+	f->fd = fd;
+	return f;
+}
+
 FILE *file_clone(const FILE *f) {
 	handle_t h = _syscall_dup(f->fd, -1, 0);
 	FILE *f2;
 	if (h < 0) return NULL;
 
-	// TODO file_wrapfd
-	f2 = malloc(sizeof *f2);
+	f2 = fdopen(h, "r+");
 	if (!f2) {
 		close(h);
 		return NULL;
-- 
cgit v1.2.3