summaryrefslogtreecommitdiff
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);