2 * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
4 * $Id: writeFile.c,v 1.14 2000/04/12 17:33:16 simonmar Exp $
6 * hPutStr Runtime Support
12 #if defined(HAVE_WINSOCK_H) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
21 writeFileObject(StgForeignPtr ptr, StgInt bytes)
24 IOFileObject* fo = (IOFileObject*)ptr;
26 /* If we've got a r/w file object in our hand, flush the
27 (input) buffer contents first.
29 if ( FILEOBJ_READABLE(fo) && FILEOBJ_JUST_READ(fo) ) {
30 fo->flags = (fo->flags & ~FILEOBJ_RW_READ) | FILEOBJ_RW_WRITE;
31 rc = flushReadBuffer(ptr);
32 if (rc < 0) return rc;
35 return (writeBuffer(ptr, bytes));
39 writeBuffer(StgForeignPtr ptr, StgInt bytes)
42 IOFileObject* fo = (IOFileObject*)ptr;
44 char *pBuf = (char *) fo->buf + fo->bufRPtr;
48 /* Disallow short writes */
49 if (bytes == 0 || fo->buf == NULL) {
57 fo->flags & FILEOBJ_WINSOCK ?
58 send(fo->fd, pBuf, bytes, 0) :
59 write(fo->fd, pBuf, bytes))) < bytes) {
61 write(fo->fd, pBuf, bytes))) < bytes) {
63 if ( count == -1 && errno == EAGAIN) {
65 return FILEOBJ_BLOCKED_WRITE;
67 else if ( count == -1 && errno != EINTR ) {
78 /* Signal that we've emptied the buffer */
85 /* ToDo: there's currently no way for writeBuf to return both a
86 * partial write and an indication that the write blocked. It needs
87 * two calls: one to get the partial result, and the next one to block.
88 * This matches Unix write/2, but is rather a waste.
92 writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len)
94 IOFileObject* fo = (IOFileObject*)ptr;
95 int count, total_count;
97 char *pBuf = (char *) buf+off;
102 /* First of all, check if we do need to flush the buffer .. */
103 /* Note - in the case of line buffering, we do not currently check
104 whether we need to flush buffer due to line terminators in the
105 buffer we're outputting */
106 if ( fo->buf != NULL && /* buffered and */
107 (fo->bufWPtr + len < (fo->bufSize)) /* there's room */
109 /* Block copying is likely to be cheaper than flush, followed by write */
110 memcpy(((char*)fo->buf + fo->bufWPtr), pBuf, len);
114 /* If we do overflow, flush current contents of the buffer and
115 directly output the chunk.
116 (no attempt at splitting up the chunk is currently made)
118 if ( fo->buf != NULL && /* buffered and */
119 (fo->bufWPtr + len >= (fo->bufSize)) /* there's not room */
122 rc = writeFileObject(ptr, fo->bufWPtr);
123 /* ToDo: undo buffer fill if we're blocking.. */
134 fo->flags & FILEOBJ_WINSOCK ?
135 send(fo->fd, pBuf, (int)len, 0) :
136 write(fo->fd, pBuf, (int)len))) < len ) {
138 write(fo->fd, pBuf, (int)len))) < len ) {
143 total_count += count;
145 } else if ( errno == EAGAIN ) {
148 return total_count; /* partial write */
150 return FILEOBJ_BLOCKED_WRITE;
151 } else if ( errno != EINTR ) {
158 total_count += count;
163 writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt off, StgInt len)
165 return (writeBuf(ptr,(StgAddr)buf, off, len));
168 /* -----------------------------------------------------------------------------
169 * write_ is just a simple wrapper around write/2 that restarts
170 * on EINTR and returns FILEOBJ_BLOCKED_WRITE on EAGAIN.
171 * -------------------------------------------------------------------------- */
174 write_(StgForeignPtr ptr, StgAddr buf, StgInt len)
176 IOFileObject* fo = (IOFileObject*)ptr;
182 fo->flags & FILEOBJ_WINSOCK ?
183 send(fo->fd, buf, (int)len, 0) :
184 write(fo->fd, buf, (int)len))) < 0 ) {
186 write(fo->fd, buf, (int)len))) < 0 ) {
188 if ( errno == EAGAIN ) {
190 return FILEOBJ_BLOCKED_WRITE;
191 } else if ( errno != EINTR ) {