/*
* (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
*
- * $Id: readFile.c,v 1.10 2000/01/18 12:42:12 simonmar Exp $
+ * $Id: readFile.c,v 1.11 2000/03/10 15:23:40 simonmar Exp $
*
* hGetContents Runtime Support
*/
}
/* Filling up a (block-buffered) buffer of length len */
+
+/* readChunk(FileObjet *, void *, int)
+ * returns:
+ * -1 error
+ * -2 object closed
+ * FILEOBJ_BLOCKED_CONN_WRITE blocking while flushing
+ * buffer of connected handle.
+ * FILEOBJ_BLOCKED_READ didn't read anything; would block
+ * n, where n > 0 read n bytes into buffer.
+ */
+
StgInt
-readChunk(StgForeignPtr ptr, StgAddr buf, StgInt len)
+readChunk(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len)
{
IOFileObject* fo = (IOFileObject*)ptr;
int count=0,rc=0, total_count;
return count;
len -= count;
- p = buf;
+ p = buf+off;
p += count;
total_count = count;
#else
read(fd, p, len))) <= 0 ) {
#endif
- if ( count == 0 ) { /* EOF */
- break;
+ /* EOF */
+ if ( count == 0 ) {
+ FILEOBJ_SET_EOF(fo);
+ return total_count;
+
+ /* Blocking */
} else if ( count == -1 && errno == EAGAIN) {
- /* ToDo: partial/blocked reads?????? Looks like we don't recover
- * from this properly.
- */
errno = 0;
- return FILEOBJ_BLOCKED_READ;
+ if (total_count > 0)
+ return total_count; /* partial read */
+ else
+ return FILEOBJ_BLOCKED_READ;
+
+ /* Error */
} else if ( count == -1 && errno != EINTR) {
cvtErrno();
stdErrno();
return -1;
- }
- total_count += count;
- len -= count;
- p += count;
+ }
}
total_count += count;
- /* ToDo: might point beyond the end of the buffer??? */
- fo->bufWPtr = total_count;
- fo->bufRPtr = 0;
return total_count;
}
/* -----------------------------------------------------------------------------
- * $Id: stgio.h,v 1.16 1999/12/08 15:47:08 simonmar Exp $
+ * $Id: stgio.h,v 1.17 2000/03/10 15:23:40 simonmar Exp $
*
* (c) The GRASP/AQUA Project, Glasgow University, 1994-1999
*
/* readFile.c */
StgInt readBlock (StgForeignPtr);
-StgInt readChunk (StgForeignPtr,StgAddr,StgInt);
+StgInt readChunk (StgForeignPtr,StgAddr,StgInt,StgInt);
StgInt readLine (StgForeignPtr);
StgInt readChar (StgForeignPtr);
/* writeError.c */
void writeErrString__ (StgAddr, StgByteArray, StgInt);
/* writeFile.c */
-StgInt writeBuf (StgForeignPtr, StgAddr, StgInt);
-StgInt writeBufBA (StgForeignPtr, StgByteArray, StgInt);
+StgInt writeBuf (StgForeignPtr, StgAddr, StgInt, StgInt);
+StgInt writeBufBA (StgForeignPtr, StgByteArray, StgInt, StgInt);
StgInt writeFileObject (StgForeignPtr, StgInt);
StgInt writeBuffer (StgForeignPtr, StgInt);
/*
* (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
*/
}
+/* 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 .. */
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.
}
}
+ total_count = 0;
+
while ((count =
(
#ifdef USE_WINSOCK
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();
}
}
- 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));
}