[project @ 2000-01-17 12:30:07 by simonmar]
[ghc-hetmet.git] / ghc / lib / std / cbits / writeFile.c
index a54ba65..5255ea9 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
  *
- * $Id: writeFile.c,v 1.3 1998/12/02 13:28:07 simonm Exp $
+ * $Id: writeFile.c,v 1.12 1999/12/08 15:47:08 simonmar Exp $
  *
  * hPutStr Runtime Support
  */
@@ -9,16 +9,20 @@
 #include "Rts.h"
 #include "stgio.h"
 
+#if defined(HAVE_WINSOCK_H) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
+#define USE_WINSOCK
+#endif
+
+#ifdef USE_WINSOCK
+#include <winsock.h>
+#endif
+
 StgInt
-writeFileObject(ptr, bytes)
-StgForeignPtr ptr;
-StgInt bytes;
+writeFileObject(StgForeignPtr ptr, StgInt bytes)
 {
     int rc=0;
     IOFileObject* fo = (IOFileObject*)ptr;
 
-    char *p = (char *) fo->buf;
-
     /* If we've got a r/w file object in our hand, flush the
        (input) buffer contents first.
     */
@@ -32,47 +36,59 @@ StgInt bytes;
 }
 
 StgInt
-writeBuffer(ptr, bytes)
-StgForeignPtr ptr;
-StgInt bytes;
+writeBuffer(StgForeignPtr ptr, StgInt bytes)
 {
-    int count, rc=0;
+    int count;
     IOFileObject* fo = (IOFileObject*)ptr;
 
-    char *p = (char *) fo->buf;
+    char *pBuf = (char *) fo->buf + fo->bufStart;
+
+    bytes -= fo->bufStart;
 
     /* Disallow short writes */
-    if (bytes == 0  || fo->buf == NULL)
+    if (bytes == 0  || fo->buf == NULL) {
+        fo->bufStart = 0;
        return 0;
+    }
 
-    if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
-       return FILEOBJ_BLOCKED_WRITE;
-
-    while ((count = write(fo->fd, fo->buf, bytes)) < bytes) {
-       if (errno != EINTR) {
+    while ((count = 
+              (
+#ifdef USE_WINSOCK
+                fo->flags & FILEOBJ_WINSOCK ?
+                send(fo->fd,  pBuf, bytes, 0) :
+                write(fo->fd, pBuf, bytes))) < bytes) {
+#else
+                write(fo->fd, pBuf, bytes))) < bytes) {
+#endif
+        if ( count == -1 && errno == EAGAIN) {
+            errno = 0;
+            return FILEOBJ_BLOCKED_WRITE;
+        }
+       else if ( count == -1 && errno != EINTR ) {
            cvtErrno();
            stdErrno();
            return -1;
        }
-       bytes -= count;
-       p += count;
+        else {
+           bytes -= count;
+           pBuf  += count;
+            fo->bufStart += count;
+        }
     }
     /* Signal that we've emptied the buffer */
-    fo->bufWPtr=0;
+    fo->bufStart = 0;
+    fo->bufWPtr  = 0;
     return 0;
 }
 
 
 StgInt
-writeBuf(ptr, buf, len)
-StgForeignPtr ptr;
-StgAddr buf;
-StgInt  len;
+writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
 {
     IOFileObject* fo = (IOFileObject*)ptr;
     int count;
     int rc = 0;
-    char *p = (char *) buf;
+    char *pBuf = (char *) buf;
 
     if (len == 0 )
        return 0;
@@ -99,32 +115,39 @@ StgInt  len;
        /* Flush buffer */
        rc = writeFileObject(ptr, fo->bufWPtr);
        /* ToDo: undo buffer fill if we're blocking.. */
+       if (rc != 0) { 
+           return rc;
+       }
     }
 
-    if (rc != 0) { 
-       return rc;
-    }
-
-    if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
-       return FILEOBJ_BLOCKED_WRITE;
-
-    /* Disallow short writes */
-    while ((count = write(fo->fd, (char *)buf, (int)len)) < len) {
-       if (errno != EINTR) {
+    while ((count = 
+               (
+#ifdef USE_WINSOCK
+                fo->flags & FILEOBJ_WINSOCK ?
+                send(fo->fd,  pBuf, (int)len, 0) :
+                write(fo->fd, pBuf, (int)len))) < len ) {
+#else
+                write(fo->fd, pBuf, (int)len))) < len ) {
+#endif
+        if ( count >= 0 ) {
+            len -= count;
+           pBuf += count;
+           continue;
+       } else if ( errno == EAGAIN ) {
+           errno = 0;
+           return FILEOBJ_BLOCKED_WRITE;
+       } else if ( errno != EINTR ) {
            cvtErrno();
            stdErrno();
            return -1;
        }
-       len -= count;
-       p += count;
     }
 
     return 0;
 }
 
 StgInt
-writeBufBA(ptr, buf, len)
-     StgForeignPtr ptr;
-StgByteArray buf;
-StgInt  len;
-{ return (writeBuf(ptr,(StgAddr)buf, len)); }
+writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt len)
+{ 
+    return (writeBuf(ptr,(StgAddr)buf, len)); 
+}