summaryrefslogtreecommitdiff
path: root/ghc/lib/std/cbits/writeFile.c
diff options
context:
space:
mode:
authorsimonmar <unknown>2000-03-10 15:23:40 +0000
committersimonmar <unknown>2000-03-10 15:23:40 +0000
commitf9a0273cd8017d27e81e314f067b0d5197918d68 (patch)
tree21f0cd2c610f5786d6eae52b3366f30ade5a9083 /ghc/lib/std/cbits/writeFile.c
parent2f4676b44b3800815c5d08a8518562e20046d082 (diff)
downloadhaskell-f9a0273cd8017d27e81e314f067b0d5197918d68.tar.gz
[project @ 2000-03-10 15:23:40 by simonmar]
Fix h{Fill,Put}Buf(BA)?. They now work in the presence of partial/blocking reads and writes, and hPutBuf now doesn't hold on to the handle while it's blocking.
Diffstat (limited to 'ghc/lib/std/cbits/writeFile.c')
-rw-r--r--ghc/lib/std/cbits/writeFile.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/ghc/lib/std/cbits/writeFile.c b/ghc/lib/std/cbits/writeFile.c
index 5255ea91eb..eed60e9baf 100644
--- a/ghc/lib/std/cbits/writeFile.c
+++ b/ghc/lib/std/cbits/writeFile.c
@@ -1,7 +1,7 @@
/*
* (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
*
- * $Id: writeFile.c,v 1.12 1999/12/08 15:47:08 simonmar Exp $
+ * $Id: writeFile.c,v 1.13 2000/03/10 15:23:40 simonmar Exp $
*
* hPutStr Runtime Support
*/
@@ -82,15 +82,21 @@ writeBuffer(StgForeignPtr ptr, StgInt bytes)
}
+/* ToDo: there's currently no way for writeBuf to return both a
+ * partial write and an indication that the write blocked. It needs
+ * two calls: one to get the partial result, and the next one to block.
+ * This matches Unix write/2, but is rather a waste.
+ */
+
StgInt
-writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
+writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len)
{
IOFileObject* fo = (IOFileObject*)ptr;
- int count;
+ int count, total_count;
int rc = 0;
- char *pBuf = (char *) buf;
+ char *pBuf = (char *) buf+off;
- if (len == 0 )
+ if (len == 0)
return 0;
/* First of all, check if we do need to flush the buffer .. */
@@ -100,10 +106,10 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
if ( fo->buf != NULL && /* buffered and */
(fo->bufWPtr + len < (fo->bufSize)) /* there's room */
) {
- /* Block copying is likely to be cheaper than, flush, followed by write */
- memcpy(((char*)fo->buf + fo->bufWPtr), buf, len);
+ /* Block copying is likely to be cheaper than flush, followed by write */
+ memcpy(((char*)fo->buf + fo->bufWPtr), pBuf, len);
fo->bufWPtr += len;
- return 0;
+ return len;
}
/* If we do overflow, flush current contents of the buffer and
directly output the chunk.
@@ -120,6 +126,8 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
}
}
+ total_count = 0;
+
while ((count =
(
#ifdef USE_WINSOCK
@@ -132,10 +140,14 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
if ( count >= 0 ) {
len -= count;
pBuf += count;
+ total_count += count;
continue;
} else if ( errno == EAGAIN ) {
errno = 0;
- return FILEOBJ_BLOCKED_WRITE;
+ if (total_count > 0)
+ return total_count; /* partial write */
+ else
+ return FILEOBJ_BLOCKED_WRITE;
} else if ( errno != EINTR ) {
cvtErrno();
stdErrno();
@@ -143,11 +155,12 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
}
}
- return 0;
+ total_count += count;
+ return total_count;
}
StgInt
-writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt len)
+writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt off, StgInt len)
{
- return (writeBuf(ptr,(StgAddr)buf, len));
+ return (writeBuf(ptr,(StgAddr)buf, off, len));
}