about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/stdio/__stdio_read.c11
-rw-r--r--src/stdio/__stdio_write.c20
-rw-r--r--src/stdio/fopen.c2
3 files changed, 28 insertions, 5 deletions
diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c
index 218bd88d..ee17a576 100644
--- a/src/stdio/__stdio_read.c
+++ b/src/stdio/__stdio_read.c
@@ -1,4 +1,11 @@
 #include "stdio_impl.h"
+#include <pthread.h>
+
+static void cleanup(void *p)
+{
+	FILE *f = p;
+	if (!f->lockcount) __unlockfile(f);
+}
 
 size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
 {
@@ -8,7 +15,9 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
 	};
 	ssize_t cnt;
 
-	cnt = syscall(SYS_readv, f->fd, iov, 2);
+	pthread_cleanup_push(cleanup, f);
+	cnt = syscall_cp(SYS_readv, f->fd, iov, 2);
+	pthread_cleanup_pop(0);
 	if (cnt <= 0) {
 		f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt);
 		f->rpos = f->rend = 0;
diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c
index 63d9c858..dd97cf68 100644
--- a/src/stdio/__stdio_write.c
+++ b/src/stdio/__stdio_write.c
@@ -1,4 +1,11 @@
 #include "stdio_impl.h"
+#include <pthread.h>
+
+static void cleanup(void *p)
+{
+	FILE *f = p;
+	if (!f->lockcount) __unlockfile(f);
+}
 
 size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
 {
@@ -10,10 +17,14 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
 	size_t rem = iov[0].iov_len + iov[1].iov_len;
 	int iovcnt = 2;
 	ssize_t cnt;
-	f->wpos = f->wbase;
 	for (;;) {
-		cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
-		if (cnt == rem) return len;
+		pthread_cleanup_push(cleanup, f);
+		cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt);
+		pthread_cleanup_pop(0);
+		if (cnt == rem) {
+			f->wpos = f->wbase = f->buf;
+			return len;
+		}
 		if (cnt < 0) {
 			f->wpos = f->wbase = f->wend = 0;
 			f->flags |= F_ERR;
@@ -21,8 +32,11 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
 		}
 		rem -= cnt;
 		if (cnt > iov[0].iov_len) {
+			f->wpos = f->wbase = f->buf;
 			cnt -= iov[0].iov_len;
 			iov++; iovcnt--;
+		} else if (iovcnt == 2) {
+			f->wbase += cnt;
 		}
 		iov[0].iov_base = (char *)iov[0].iov_base + cnt;
 		iov[0].iov_len -= cnt;
diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c
index 469de6f0..084cc73c 100644
--- a/src/stdio/fopen.c
+++ b/src/stdio/fopen.c
@@ -21,7 +21,7 @@ FILE *fopen(const char *filename, const char *mode)
 	if (*mode == 'w') flags |= O_TRUNC;
 	if (*mode == 'a') flags |= O_APPEND;
 
-	fd = syscall(SYS_open, filename, flags|O_LARGEFILE, 0666);
+	fd = syscall_cp(SYS_open, filename, flags|O_LARGEFILE, 0666);
 	if (fd < 0) return 0;
 
 	f = __fdopen(fd, mode);