71e5a23d268ab1b1d0b93019c06cc4f554ce9c6f
[ghc-hetmet.git] / ghc / lib / std / cbits / writeFile.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: writeFile.c,v 1.6 1999/07/12 10:43:13 sof Exp $
5  *
6  * hPutStr Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 #if defined(HAVE_WINSOCK_H) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
13 #define USE_WINSOCK
14 #endif
15
16 #ifdef USE_WINSOCK
17 #include <winsock.h>
18 #endif
19
20 StgInt
21 writeFileObject(ptr, bytes)
22 StgForeignPtr ptr;
23 StgInt bytes;
24 {
25     int rc=0;
26     IOFileObject* fo = (IOFileObject*)ptr;
27
28     char *p = (char *) fo->buf;
29
30     /* If we've got a r/w file object in our hand, flush the
31        (input) buffer contents first.
32     */
33     if ( FILEOBJ_READABLE(fo) && FILEOBJ_JUST_READ(fo) ) {
34        fo->flags = (fo->flags & ~FILEOBJ_RW_READ) | FILEOBJ_RW_WRITE;
35        rc = flushReadBuffer(ptr);
36        if (rc < 0) return rc;
37     }
38
39     return (writeBuffer(ptr, bytes));
40 }
41
42 StgInt
43 writeBuffer(ptr, bytes)
44 StgForeignPtr ptr;
45 StgInt bytes;
46 {
47     int count, rc=0;
48     IOFileObject* fo = (IOFileObject*)ptr;
49
50     char *p = (char *) fo->buf;
51
52     /* Disallow short writes */
53     if (bytes == 0  || fo->buf == NULL)
54         return 0;
55
56     if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
57        return FILEOBJ_BLOCKED_WRITE;
58
59     while ((count = 
60                (
61 #ifdef USE_WINSOCK
62                  fo->flags & FILEOBJ_WINSOCK ?
63                  send(fo->fd, fo->buf, bytes, 0) :
64                  write(fo->fd, fo->buf, bytes))) < bytes) {
65 #else
66                  write(fo->fd, fo->buf, bytes))) < bytes) {
67 #endif
68         if (errno != EINTR) {
69             cvtErrno();
70             stdErrno();
71             return -1;
72         }
73         bytes -= count;
74         p += count;
75     }
76     /* Signal that we've emptied the buffer */
77     fo->bufWPtr=0;
78     return 0;
79 }
80
81
82 StgInt
83 writeBuf(ptr, buf, len)
84 StgForeignPtr ptr;
85 StgAddr buf;
86 StgInt  len;
87 {
88     IOFileObject* fo = (IOFileObject*)ptr;
89     int count;
90     int rc = 0;
91     char *p = (char *) buf;
92
93     if (len == 0 )
94         return 0;
95
96     /* First of all, check if we do need to flush the buffer .. */
97     /* Note - in the case of line buffering, we do not currently check
98        whether we need to flush buffer due to line terminators in the
99        buffer we're outputting */
100     if ( fo->buf != NULL                     &&   /* buffered and */
101          (fo->bufWPtr + len < (fo->bufSize))      /* there's room */
102        ) {
103        /* Block copying is likely to be cheaper than, flush, followed by write */
104        memcpy(((char*)fo->buf + fo->bufWPtr), buf, len);
105        fo->bufWPtr += len;
106        return 0;
107     }
108     /* If we do overflow, flush current contents of the buffer and
109        directly output the chunk.
110        (no attempt at splitting up the chunk is currently made)
111     */       
112     if ( fo->buf != NULL                     &&    /* buffered and */
113          (fo->bufWPtr + len >= (fo->bufSize))       /* there's not room */
114        ) {
115        /* Flush buffer */
116        rc = writeFileObject(ptr, fo->bufWPtr);
117        /* ToDo: undo buffer fill if we're blocking.. */
118     }
119
120     if (rc != 0) { 
121        return rc;
122     }
123
124     if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
125        return FILEOBJ_BLOCKED_WRITE;
126
127     /* Disallow short writes */
128     while ((count = 
129                (
130 #ifdef USE_WINSOCK
131                  fo->flags & FILEOBJ_WINSOCK ?
132                  send(fo->fd,  (char*)buf, (int)len, 0) :
133                  write(fo->fd, (char*)buf, (int)len))) < len ) {
134 #else
135                  write(fo->fd, (char*)buf, (int)len))) < len ) {
136 #endif
137         if (errno != EINTR) {
138             cvtErrno();
139             stdErrno();
140             return -1;
141         }
142         len -= count;
143         p += count;
144     }
145
146     return 0;
147 }
148
149 StgInt
150 writeBufBA(ptr, buf, len)
151      StgForeignPtr ptr;
152 StgByteArray buf;
153 StgInt  len;
154 { return (writeBuf(ptr,(StgAddr)buf, len)); }