2 * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
4 * $Id: seekFile.c,v 1.5 2000/01/17 12:30:07 simonmar Exp $
6 * hSeek and hIsSeekable Runtime Support
12 #ifdef HAVE_SYS_TYPES_H
13 #include <sys/types.h>
16 #ifdef HAVE_SYS_STAT_H
20 /* Invoked by IO.hSeek only */
22 seekFile(StgForeignPtr ptr, StgInt whence, StgInt size, StgByteArray d)
24 IOFileObject* fo = (IOFileObject*)ptr;
31 case 0: whence=SEEK_SET; break;
32 case 1: whence=SEEK_CUR; break;
33 case 2: whence=SEEK_END; break;
34 default: whence=SEEK_SET; /* Should never happen, really */
38 * We need to snatch the offset out of an MP_INT. The bits are there sans sign,
39 * which we pick up from our size parameter. If abs(size) is greater than 1,
40 * this integer is just too big.
45 offset = -*(StgInt *) d;
51 offset = *(StgInt *) d;
54 ghc_errtype = ERR_INVALIDARGUMENT;
55 ghc_errstr = "offset out of range";
59 /* If we're doing a relative seek, see if we cannot deal
60 * with the request without flushing the buffer..
62 * Note: the wording in the report is vague here, but
63 * we only avoid flushing on *input* buffers and *not* output ones.
65 if ( whence == SEEK_CUR &&
66 (FILEOBJ_READABLE(fo) && !FILEOBJ_WRITEABLE(fo) &&
67 (fo->bufRPtr + (int)offset) < fo->bufWPtr &&
68 (fo->bufRPtr + (int)offset) >= 0) ) { /* The input buffer case */
69 fo->bufRPtr += (int)offset;
71 } else if ( whence == SEEK_CUR && (FILEOBJ_READABLE(fo) && !FILEOBJ_WRITEABLE(fo)) ) {
72 /* We're seeking outside the input buffer,
73 record delta so that we can adjust the file position
74 reported from the underlying fd to get
75 at the real position we're at when we take into account
78 posn_delta = fo->bufWPtr - fo->bufRPtr; /* number of chars left in the buffer */
79 if (posn_delta < 0) posn_delta=0;
82 /* If we cannot seek within our current buffer, flush it. */
83 rc = flushBuffer(ptr);
84 if (rc < 0) return rc;
86 /* Try to find out the file type */
87 while (fstat(fo->fd, &sb) < 0) {
95 if (S_ISFIFO(sb.st_mode)) {
96 ghc_errtype = ERR_UNSUPPORTEDOPERATION;
97 ghc_errstr = "can't seek on a pipe";
100 while ( lseek(fo->fd, offset-posn_delta, whence) == -1) {
101 if (errno != EINTR) {
108 FILEOBJ_CLEAR_EOF(fo);
112 /* Invoked by IO.hSeek only */
114 seekFile_int64(StgForeignPtr ptr, StgInt whence, StgInt64 d)
116 IOFileObject* fo = (IOFileObject*)ptr;
123 case 0: whence=SEEK_SET; break;
124 case 1: whence=SEEK_CUR; break;
125 case 2: whence=SEEK_END; break;
126 default: whence=SEEK_SET; break; /* Should never happen, really */
129 /* If we're doing a relative seek, see if we cannot deal
130 * with the request without flushing the buffer..
132 * Note: the wording in the report is vague here, but
133 * we only avoid flushing on *input* buffers and *not* output ones.
135 if ( whence == SEEK_CUR &&
136 (FILEOBJ_READABLE(fo) && !FILEOBJ_WRITEABLE(fo) &&
137 (fo->bufRPtr + (int)offset) < fo->bufWPtr &&
138 (fo->bufRPtr + (int)offset) >= 0) ) { /* The input buffer case */
139 fo->bufRPtr += (int)offset;
141 } else if ( whence == SEEK_CUR && (FILEOBJ_READABLE(fo) && !FILEOBJ_WRITEABLE(fo)) ) {
142 /* We're seeking outside the input buffer,
143 record delta so that we can adjust the file position
144 reported from the underlying fd to get
145 at the real position we're at when we take into account
148 posn_delta = fo->bufWPtr - fo->bufRPtr; /* number of chars left in the buffer */
149 if (posn_delta < 0) posn_delta=0;
152 /* If we cannot seek within our current buffer, flush it. */
153 rc = flushBuffer(ptr);
154 if (rc < 0) return rc;
156 /* Try to find out the file type & size for a physical file */
157 while (fstat(fo->fd, &sb) < 0) {
158 /* highly unlikely */
159 if (errno != EINTR) {
165 if (S_ISFIFO(sb.st_mode)) {
166 ghc_errtype = ERR_UNSUPPORTEDOPERATION;
167 ghc_errstr = "can't seek on a pipe";
170 while ( lseek(fo->fd, offset-posn_delta, whence) == -1) {
171 if (errno != EINTR) {
178 FILEOBJ_CLEAR_EOF(fo);
183 seekFileP(StgForeignPtr ptr)
185 IOFileObject* fo = (IOFileObject*)ptr;
188 /* Try to find out the file type */
189 while (fstat(fo->fd, &sb) < 0) {
190 /* highly unlikely */
191 if (errno != EINTR) {
197 /* Pipes are not okay.. */
198 if (S_ISFIFO(sb.st_mode)) {
201 /* ..for now, everything else is */