+ }
+ /* Clear EOF */
+ FILEOBJ_CLEAR_EOF(fo);
+ return 0;
+}
+
+/* Invoked by IO.hSeek only */
+StgInt
+seekFile_int64(ptr, whence, d)
+StgForeignPtr ptr;
+StgInt whence;
+StgInt64 d;
+{
+ IOFileObject* fo = (IOFileObject*)ptr;
+ struct stat sb;
+ off_t offset = d;
+ int posn_delta =0;
+ int rc = 0;
+
+ switch (whence) {
+ case 0: whence=SEEK_SET; break;
+ case 1: whence=SEEK_CUR; break;
+ case 2: whence=SEEK_END; break;
+ default: whence=SEEK_SET; break; /* Should never happen, really */
+ }
+
+ /* If we're doing a relative seek, see if we cannot deal
+ * with the request without flushing the buffer..
+ *
+ * Note: the wording in the report is vague here, but
+ * we only avoid flushing on *input* buffers and *not* output ones.
+ */
+ if ( whence == SEEK_CUR &&
+ (FILEOBJ_READABLE(fo) && !FILEOBJ_WRITEABLE(fo) &&
+ (fo->bufRPtr + (int)offset) < fo->bufWPtr &&
+ (fo->bufRPtr + (int)offset) >= 0) ) { /* The input buffer case */
+ fo->bufRPtr += (int)offset;
+ return 0;
+ } else if ( whence == SEEK_CUR && (FILEOBJ_READABLE(fo) && !FILEOBJ_WRITEABLE(fo)) ) {
+ /* We're seeking outside the input buffer,
+ record delta so that we can adjust the file position
+ reported from the underlying fd to get
+ at the real position we're at when we take into account
+ buffering.
+ */
+ posn_delta = fo->bufWPtr - fo->bufRPtr; /* number of chars left in the buffer */
+ if (posn_delta < 0) posn_delta=0;
+ }
+
+ /* If we cannot seek within our current buffer, flush it. */
+ rc = flushBuffer(ptr);
+ if (rc < 0) return rc;
+
+ /* Try to find out the file type & size for a physical file */
+ while (fstat(fo->fd, &sb) < 0) {
+ /* highly unlikely */
+ if (errno != EINTR) {
+ cvtErrno();
+ stdErrno();