1 {-# OPTIONS -fno-implicit-prelude -#include "HsBase.h" #-}
6 -----------------------------------------------------------------------------
9 -- Copyright : (c) The University of Glasgow, 1994-2001
10 -- License : see libraries/base/LICENSE
12 -- Maintainer : libraries@haskell.org
13 -- Stability : internal
14 -- Portability : non-portable
16 -- This module defines the basic operations on I\/O \"handles\".
18 -----------------------------------------------------------------------------
21 withHandle, withHandle', withHandle_,
22 wantWritableHandle, wantReadableHandle, wantSeekableHandle,
24 newEmptyBuffer, allocateBuffer, readCharFromBuffer, writeCharIntoBuffer,
25 flushWriteBufferOnly, flushWriteBuffer, flushReadBuffer, fillReadBuffer,
26 readRawBuffer, readRawBufferPtr,
27 writeRawBuffer, writeRawBufferPtr,
30 {- ought to be unnecessary, but just in case.. -}
31 write_off, write_rawBuffer,
32 read_off, read_rawBuffer,
34 ioe_closedHandle, ioe_EOF, ioe_notReadable, ioe_notWritable,
36 stdin, stdout, stderr,
37 IOMode(..), IOModeEx(..), openFile, openFileEx, openFd, fdToHandle,
38 hFileSize, hIsEOF, isEOF, hLookAhead, hSetBuffering, hSetBinaryMode,
39 hFlush, hDuplicate, hDuplicateTo,
43 HandlePosn(..), hGetPosn, hSetPosn,
44 SeekMode(..), hSeek, hTell,
46 hIsOpen, hIsClosed, hIsReadable, hIsWritable, hGetBuffering, hIsSeekable,
47 hSetEcho, hGetEcho, hIsTerminalDevice,
62 import System.IO.Error
69 import GHC.Read ( Read )
74 import GHC.Num ( Integer(..), Num(..) )
76 import GHC.Real ( toInteger )
80 -- -----------------------------------------------------------------------------
83 -- hWaitForInput blocks (should use a timeout)
85 -- unbuffered hGetLine is a bit dodgy
87 -- hSetBuffering: can't change buffering on a stream,
88 -- when the read buffer is non-empty? (no way to flush the buffer)
90 -- ---------------------------------------------------------------------------
91 -- Are files opened by default in text or binary mode, if the user doesn't
94 dEFAULT_OPEN_IN_BINARY_MODE = False :: Bool
96 -- ---------------------------------------------------------------------------
97 -- Creating a new handle
99 newFileHandle :: (MVar Handle__ -> IO ()) -> Handle__ -> IO Handle
100 newFileHandle finalizer hc = do
102 addMVarFinalizer m (finalizer m)
103 return (FileHandle m)
105 -- ---------------------------------------------------------------------------
106 -- Working with Handles
109 In the concurrent world, handles are locked during use. This is done
110 by wrapping an MVar around the handle which acts as a mutex over
111 operations on the handle.
113 To avoid races, we use the following bracketing operations. The idea
114 is to obtain the lock, do some operation and replace the lock again,
115 whether the operation succeeded or failed. We also want to handle the
116 case where the thread receives an exception while processing the IO
117 operation: in these cases we also want to relinquish the lock.
119 There are three versions of @withHandle@: corresponding to the three
120 possible combinations of:
122 - the operation may side-effect the handle
123 - the operation may return a result
125 If the operation generates an error or an exception is raised, the
126 original handle is always replaced [ this is the case at the moment,
127 but we might want to revisit this in the future --SDM ].
130 {-# INLINE withHandle #-}
131 withHandle :: String -> Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
132 withHandle fun h@(FileHandle m) act = withHandle' fun h m act
133 withHandle fun h@(DuplexHandle m _) act = withHandle' fun h m act
135 withHandle' :: String -> Handle -> MVar Handle__
136 -> (Handle__ -> IO (Handle__,a)) -> IO a
137 withHandle' fun h m act =
140 checkBufferInvariants h_
141 (h',v) <- catchException (act h_)
142 (\ err -> putMVar m h_ >>
144 IOException ex -> ioError (augmentIOError ex fun h h_)
146 checkBufferInvariants h'
150 {-# INLINE withHandle_ #-}
151 withHandle_ :: String -> Handle -> (Handle__ -> IO a) -> IO a
152 withHandle_ fun h@(FileHandle m) act = withHandle_' fun h m act
153 withHandle_ fun h@(DuplexHandle m _) act = withHandle_' fun h m act
155 withHandle_' fun h m act =
158 checkBufferInvariants h_
159 v <- catchException (act h_)
160 (\ err -> putMVar m h_ >>
162 IOException ex -> ioError (augmentIOError ex fun h h_)
164 checkBufferInvariants h_
168 withAllHandles__ :: String -> Handle -> (Handle__ -> IO Handle__) -> IO ()
169 withAllHandles__ fun h@(FileHandle m) act = withHandle__' fun h m act
170 withAllHandles__ fun h@(DuplexHandle r w) act = do
171 withHandle__' fun h r act
172 withHandle__' fun h w act
174 withHandle__' fun h m act =
177 checkBufferInvariants h_
178 h' <- catchException (act h_)
179 (\ err -> putMVar m h_ >>
181 IOException ex -> ioError (augmentIOError ex fun h h_)
183 checkBufferInvariants h'
187 augmentIOError (IOError _ iot _ str fp) fun h h_
188 = IOError (Just h) iot fun str filepath
189 where filepath | Just _ <- fp = fp
190 | otherwise = Just (haFilePath h_)
192 -- ---------------------------------------------------------------------------
193 -- Wrapper for write operations.
195 wantWritableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
196 wantWritableHandle fun h@(FileHandle m) act
197 = wantWritableHandle' fun h m act
198 wantWritableHandle fun h@(DuplexHandle _ m) act
199 = wantWritableHandle' fun h m act
200 -- ToDo: in the Duplex case, we don't need to checkWritableHandle
203 :: String -> Handle -> MVar Handle__
204 -> (Handle__ -> IO a) -> IO a
205 wantWritableHandle' fun h m act
206 = withHandle_' fun h m (checkWritableHandle act)
208 checkWritableHandle act handle_
209 = case haType handle_ of
210 ClosedHandle -> ioe_closedHandle
211 SemiClosedHandle -> ioe_closedHandle
212 ReadHandle -> ioe_notWritable
213 ReadWriteHandle -> do
214 let ref = haBuffer handle_
217 if not (bufferIsWritable buf)
218 then do b <- flushReadBuffer (haFD handle_) buf
219 return b{ bufState=WriteBuffer }
221 writeIORef ref new_buf
223 _other -> act handle_
225 -- ---------------------------------------------------------------------------
226 -- Wrapper for read operations.
228 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
229 wantReadableHandle fun h@(FileHandle m) act
230 = wantReadableHandle' fun h m act
231 wantReadableHandle fun h@(DuplexHandle m _) act
232 = wantReadableHandle' fun h m act
233 -- ToDo: in the Duplex case, we don't need to checkReadableHandle
236 :: String -> Handle -> MVar Handle__
237 -> (Handle__ -> IO a) -> IO a
238 wantReadableHandle' fun h m act
239 = withHandle_' fun h m (checkReadableHandle act)
241 checkReadableHandle act handle_ =
242 case haType handle_ of
243 ClosedHandle -> ioe_closedHandle
244 SemiClosedHandle -> ioe_closedHandle
245 AppendHandle -> ioe_notReadable
246 WriteHandle -> ioe_notReadable
247 ReadWriteHandle -> do
248 let ref = haBuffer handle_
250 when (bufferIsWritable buf) $ do
251 new_buf <- flushWriteBuffer (haFD handle_) (haIsStream handle_) buf
252 writeIORef ref new_buf{ bufState=ReadBuffer }
254 _other -> act handle_
256 -- ---------------------------------------------------------------------------
257 -- Wrapper for seek operations.
259 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
260 wantSeekableHandle fun h@(DuplexHandle _ _) _act =
261 ioException (IOError (Just h) IllegalOperation fun
262 "handle is not seekable" Nothing)
263 wantSeekableHandle fun h@(FileHandle m) act =
264 withHandle_' fun h m (checkSeekableHandle act)
266 checkSeekableHandle act handle_ =
267 case haType handle_ of
268 ClosedHandle -> ioe_closedHandle
269 SemiClosedHandle -> ioe_closedHandle
270 AppendHandle -> ioe_notSeekable
271 _ | haIsBin handle_ || tEXT_MODE_SEEK_ALLOWED -> act handle_
272 | otherwise -> ioe_notSeekable_notBin
274 -- -----------------------------------------------------------------------------
277 ioe_closedHandle, ioe_EOF,
278 ioe_notReadable, ioe_notWritable,
279 ioe_notSeekable, ioe_notSeekable_notBin :: IO a
281 ioe_closedHandle = ioException
282 (IOError Nothing IllegalOperation ""
283 "handle is closed" Nothing)
284 ioe_EOF = ioException
285 (IOError Nothing EOF "" "" Nothing)
286 ioe_notReadable = ioException
287 (IOError Nothing IllegalOperation ""
288 "handle is not open for reading" Nothing)
289 ioe_notWritable = ioException
290 (IOError Nothing IllegalOperation ""
291 "handle is not open for writing" Nothing)
292 ioe_notSeekable = ioException
293 (IOError Nothing IllegalOperation ""
294 "handle is not seekable" Nothing)
295 ioe_notSeekable_notBin = ioException
296 (IOError Nothing IllegalOperation ""
297 "seek operations on text-mode handles are not allowed on this platform"
300 ioe_bufsiz :: Int -> IO a
301 ioe_bufsiz n = ioException
302 (IOError Nothing InvalidArgument "hSetBuffering"
303 ("illegal buffer size " ++ showsPrec 9 n []) Nothing)
304 -- 9 => should be parens'ified.
306 -- -----------------------------------------------------------------------------
309 -- For a duplex handle, we arrange that the read side points to the write side
310 -- (and hence keeps it alive if the read side is alive). This is done by
311 -- having the haOtherSide field of the read side point to the read side.
312 -- The finalizer is then placed on the write side, and the handle only gets
313 -- finalized once, when both sides are no longer required.
315 stdHandleFinalizer :: MVar Handle__ -> IO ()
316 stdHandleFinalizer m = do
318 flushWriteBufferOnly h_
320 handleFinalizer :: MVar Handle__ -> IO ()
321 handleFinalizer m = do
324 -- hClose puts both the fd and the handle's type
325 -- into a closed state, so it's a bit excessive
326 -- to test for both here, but caution sometimes
329 case haType h_ of { ClosedHandle{} -> True; _ -> False }
330 fd = fromIntegral (haFD h_)
332 when (not alreadyClosed && fd /= -1) $ do
333 flushWriteBufferOnly h_
335 #ifdef mingw32_TARGET_OS
336 (closeFd (haIsStream h_) fd >> return ())
338 (c_close fd >> return ())
341 -- ---------------------------------------------------------------------------
342 -- Grimy buffer operations
345 checkBufferInvariants h_ = do
346 let ref = haBuffer h_
347 Buffer{ bufWPtr=w, bufRPtr=r, bufSize=size, bufState=state } <- readIORef ref
352 && ( r /= w || (r == 0 && w == 0) )
353 && ( state /= WriteBuffer || r == 0 )
354 && ( state /= WriteBuffer || w < size ) -- write buffer is never full
356 then error "buffer invariant violation"
359 checkBufferInvariants h_ = return ()
362 newEmptyBuffer :: RawBuffer -> BufferState -> Int -> Buffer
363 newEmptyBuffer b state size
364 = Buffer{ bufBuf=b, bufRPtr=0, bufWPtr=0, bufSize=size, bufState=state }
366 allocateBuffer :: Int -> BufferState -> IO Buffer
367 allocateBuffer sz@(I# size) state = IO $ \s ->
368 #ifdef mingw32_TARGET_OS
369 -- To implement asynchronous I/O under Win32, we have to pass
370 -- buffer references to external threads that handles the
371 -- filling/emptying of their contents. Hence, the buffer cannot
372 -- be moved around by the GC.
373 case newPinnedByteArray# size s of { (# s, b #) ->
375 case newByteArray# size s of { (# s, b #) ->
377 (# s, newEmptyBuffer b state sz #) }
379 writeCharIntoBuffer :: RawBuffer -> Int -> Char -> IO Int
380 writeCharIntoBuffer slab (I# off) (C# c)
381 = IO $ \s -> case writeCharArray# slab off c s of
382 s -> (# s, I# (off +# 1#) #)
384 readCharFromBuffer :: RawBuffer -> Int -> IO (Char, Int)
385 readCharFromBuffer slab (I# off)
386 = IO $ \s -> case readCharArray# slab off s of
387 (# s, c #) -> (# s, (C# c, I# (off +# 1#)) #)
389 getBuffer :: FD -> BufferState -> IO (IORef Buffer, BufferMode)
390 getBuffer fd state = do
391 buffer <- allocateBuffer dEFAULT_BUFFER_SIZE state
392 ioref <- newIORef buffer
396 | is_tty = LineBuffering
397 | otherwise = BlockBuffering Nothing
399 return (ioref, buffer_mode)
401 mkUnBuffer :: IO (IORef Buffer)
403 buffer <- allocateBuffer 1 ReadBuffer
406 -- flushWriteBufferOnly flushes the buffer iff it contains pending write data.
407 flushWriteBufferOnly :: Handle__ -> IO ()
408 flushWriteBufferOnly h_ = do
412 new_buf <- if bufferIsWritable buf
413 then flushWriteBuffer fd (haIsStream h_) buf
415 writeIORef ref new_buf
417 -- flushBuffer syncs the file with the buffer, including moving the
418 -- file pointer backwards in the case of a read buffer.
419 flushBuffer :: Handle__ -> IO ()
421 let ref = haBuffer h_
426 ReadBuffer -> flushReadBuffer (haFD h_) buf
427 WriteBuffer -> flushWriteBuffer (haFD h_) (haIsStream h_) buf
429 writeIORef ref flushed_buf
431 -- When flushing a read buffer, we seek backwards by the number of
432 -- characters in the buffer. The file descriptor must therefore be
433 -- seekable: attempting to flush the read buffer on an unseekable
434 -- handle is not allowed.
436 flushReadBuffer :: FD -> Buffer -> IO Buffer
437 flushReadBuffer fd buf
438 | bufferEmpty buf = return buf
440 let off = negate (bufWPtr buf - bufRPtr buf)
442 puts ("flushReadBuffer: new file offset = " ++ show off ++ "\n")
444 throwErrnoIfMinus1Retry "flushReadBuffer"
445 (c_lseek (fromIntegral fd) (fromIntegral off) sEEK_CUR)
446 return buf{ bufWPtr=0, bufRPtr=0 }
448 flushWriteBuffer :: FD -> Bool -> Buffer -> IO Buffer
449 flushWriteBuffer fd is_stream buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w } = do
452 puts ("flushWriteBuffer, fd=" ++ show fd ++ ", bytes=" ++ show bytes ++ "\n")
455 then return (buf{ bufRPtr=0, bufWPtr=0 })
457 res <- writeRawBuffer "flushWriteBuffer" (fromIntegral fd) is_stream b
458 (fromIntegral r) (fromIntegral bytes)
459 let res' = fromIntegral res
461 then flushWriteBuffer fd is_stream (buf{ bufRPtr = r + res' })
462 else return buf{ bufRPtr=0, bufWPtr=0 }
464 fillReadBuffer :: FD -> Bool -> Bool -> Buffer -> IO Buffer
465 fillReadBuffer fd is_line is_stream
466 buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w, bufSize=size } =
467 -- buffer better be empty:
468 assert (r == 0 && w == 0) $ do
469 fillReadBufferLoop fd is_line is_stream buf b w size
471 -- For a line buffer, we just get the first chunk of data to arrive,
472 -- and don't wait for the whole buffer to be full (but we *do* wait
473 -- until some data arrives). This isn't really line buffering, but it
474 -- appears to be what GHC has done for a long time, and I suspect it
475 -- is more useful than line buffering in most cases.
477 fillReadBufferLoop fd is_line is_stream buf b w size = do
479 if bytes == 0 -- buffer full?
480 then return buf{ bufRPtr=0, bufWPtr=w }
483 puts ("fillReadBufferLoop: bytes = " ++ show bytes ++ "\n")
485 res <- readRawBuffer "fillReadBuffer" fd is_stream b
486 (fromIntegral w) (fromIntegral bytes)
487 let res' = fromIntegral res
489 puts ("fillReadBufferLoop: res' = " ++ show res' ++ "\n")
494 else return buf{ bufRPtr=0, bufWPtr=w }
495 else if res' < bytes && not is_line
496 then fillReadBufferLoop fd is_line is_stream buf b (w+res') size
497 else return buf{ bufRPtr=0, bufWPtr=w+res' }
500 -- Low level routines for reading/writing to (raw)buffers:
502 #ifndef mingw32_TARGET_OS
503 readRawBuffer :: String -> FD -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
504 readRawBuffer loc fd is_stream buf off len =
505 throwErrnoIfMinus1RetryMayBlock loc
506 (read_rawBuffer fd is_stream buf off len)
509 readRawBufferPtr :: String -> FD -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
510 readRawBufferPtr loc fd is_stream buf off len =
511 throwErrnoIfMinus1RetryMayBlock loc
512 (read_off fd is_stream buf off len)
515 writeRawBuffer :: String -> FD -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
516 writeRawBuffer loc fd is_stream buf off len =
517 throwErrnoIfMinus1RetryMayBlock loc
518 (write_rawBuffer (fromIntegral fd) is_stream buf off len)
521 writeRawBufferPtr :: String -> FD -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
522 writeRawBufferPtr loc fd is_stream buf off len =
523 throwErrnoIfMinus1RetryMayBlock loc
524 (write_off (fromIntegral fd) is_stream buf off len)
527 foreign import ccall unsafe "__hscore_PrelHandle_read"
528 read_rawBuffer :: FD -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
530 foreign import ccall unsafe "__hscore_PrelHandle_read"
531 read_off :: FD -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
533 foreign import ccall unsafe "__hscore_PrelHandle_write"
534 write_rawBuffer :: CInt -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
536 foreign import ccall unsafe "__hscore_PrelHandle_write"
537 write_off :: CInt -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
540 readRawBuffer :: String -> FD -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
541 readRawBuffer loc fd is_stream buf off len = do
542 (l, rc) <- asyncReadBA fd (if is_stream then 1 else 0) (fromIntegral len) off buf
545 ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)
546 else return (fromIntegral l)
548 readRawBufferPtr :: String -> FD -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
549 readRawBufferPtr loc fd is_stream buf off len = do
550 (l, rc) <- asyncRead fd (if is_stream then 1 else 0) (fromIntegral len) (buf `plusPtr` off)
553 ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)
554 else return (fromIntegral l)
556 writeRawBuffer :: String -> FD -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
557 writeRawBuffer loc fd is_stream buf off len = do
558 (l, rc) <- asyncWriteBA fd (if is_stream then 1 else 0) (fromIntegral len) off buf
561 ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)
562 else return (fromIntegral l)
564 writeRawBufferPtr :: String -> FD -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
565 writeRawBufferPtr loc fd is_stream buf off len = do
566 (l, rc) <- asyncWrite fd (if is_stream then 1 else 0) (fromIntegral len) (buf `plusPtr` off)
569 ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)
570 else return (fromIntegral l)
572 foreign import ccall unsafe "__hscore_PrelHandle_read"
573 read_rawBuffer :: FD -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
575 foreign import ccall unsafe "__hscore_PrelHandle_read"
576 read_off :: FD -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
578 foreign import ccall unsafe "__hscore_PrelHandle_write"
579 write_rawBuffer :: CInt -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
581 foreign import ccall unsafe "__hscore_PrelHandle_write"
582 write_off :: CInt -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
586 -- ---------------------------------------------------------------------------
589 -- Three handles are allocated during program initialisation. The first
590 -- two manage input or output from the Haskell program's standard input
591 -- or output channel respectively. The third manages output to the
592 -- standard error channel. These handles are initially open.
599 stdin = unsafePerformIO $ do
600 -- ToDo: acquire lock
601 setNonBlockingFD fd_stdin
602 (buf, bmode) <- getBuffer fd_stdin ReadBuffer
603 mkStdHandle fd_stdin "<stdin>" ReadHandle buf bmode
606 stdout = unsafePerformIO $ do
607 -- ToDo: acquire lock
608 -- We don't set non-blocking mode on stdout or sterr, because
609 -- some shells don't recover properly.
610 -- setNonBlockingFD fd_stdout
611 (buf, bmode) <- getBuffer fd_stdout WriteBuffer
612 mkStdHandle fd_stdout "<stdout>" WriteHandle buf bmode
615 stderr = unsafePerformIO $ do
616 -- ToDo: acquire lock
617 -- We don't set non-blocking mode on stdout or sterr, because
618 -- some shells don't recover properly.
619 -- setNonBlockingFD fd_stderr
621 mkStdHandle fd_stderr "<stderr>" WriteHandle buf NoBuffering
623 -- ---------------------------------------------------------------------------
624 -- Opening and Closing Files
627 Computation `openFile file mode' allocates and returns a new, open
628 handle to manage the file `file'. It manages input if `mode'
629 is `ReadMode', output if `mode' is `WriteMode' or `AppendMode',
630 and both input and output if mode is `ReadWriteMode'.
632 If the file does not exist and it is opened for output, it should be
633 created as a new file. If `mode' is `WriteMode' and the file
634 already exists, then it should be truncated to zero length. The
635 handle is positioned at the end of the file if `mode' is
636 `AppendMode', and otherwise at the beginning (in which case its
637 internal position is 0).
639 Implementations should enforce, locally to the Haskell process,
640 multiple-reader single-writer locking on files, which is to say that
641 there may either be many handles on the same file which manage input,
642 or just one handle on the file which manages output. If any open or
643 semi-closed handle is managing a file for output, no new handle can be
644 allocated for that file. If any open or semi-closed handle is
645 managing a file for input, new handles can only be allocated if they
646 do not manage output.
648 Two files are the same if they have the same absolute name. An
649 implementation is free to impose stricter conditions.
655 deriving (Eq, Read, Show)
657 addFilePathToIOError fun fp (IOError h iot _ str _)
658 = IOError h iot fun str (Just fp)
660 openFile :: FilePath -> IOMode -> IO Handle
663 (openFile' fp (if dEFAULT_OPEN_IN_BINARY_MODE
666 (\e -> ioError (addFilePathToIOError "openFile" fp e))
668 openFileEx :: FilePath -> IOModeEx -> IO Handle
672 (\e -> ioError (addFilePathToIOError "openFileEx" fp e))
675 openFile' filepath ex_mode =
676 withCString filepath $ \ f ->
681 BinaryMode bmo -> (bmo, True)
682 TextMode tmo -> (tmo, False)
684 oflags1 = case mode of
685 ReadMode -> read_flags
686 WriteMode -> write_flags
687 ReadWriteMode -> rw_flags
688 AppendMode -> append_flags
690 truncate | WriteMode <- mode = True
697 oflags = oflags1 .|. binary_flags
700 -- the old implementation had a complicated series of three opens,
701 -- which is perhaps because we have to be careful not to open
702 -- directories. However, the man pages I've read say that open()
703 -- always returns EISDIR if the file is a directory and was opened
704 -- for writing, so I think we're ok with a single open() here...
705 fd <- fromIntegral `liftM`
706 throwErrnoIfMinus1Retry "openFile"
707 (c_open f (fromIntegral oflags) 0o666)
709 openFd fd Nothing filepath mode binary truncate
710 -- ASSERT: if we just created the file, then openFd won't fail
711 -- (so we don't need to worry about removing the newly created file
712 -- in the event of an error).
715 std_flags = o_NONBLOCK .|. o_NOCTTY
716 output_flags = std_flags .|. o_CREAT
717 read_flags = std_flags .|. o_RDONLY
718 write_flags = output_flags .|. o_WRONLY
719 rw_flags = output_flags .|. o_RDWR
720 append_flags = write_flags .|. o_APPEND
722 -- ---------------------------------------------------------------------------
725 openFd :: FD -> Maybe FDType -> FilePath -> IOMode -> Bool -> Bool -> IO Handle
726 openFd fd mb_fd_type filepath mode binary truncate = do
727 -- turn on non-blocking mode
730 let (ha_type, write) =
732 ReadMode -> ( ReadHandle, False )
733 WriteMode -> ( WriteHandle, True )
734 ReadWriteMode -> ( ReadWriteHandle, True )
735 AppendMode -> ( AppendHandle, True )
737 -- open() won't tell us if it was a directory if we only opened for
738 -- reading, so check again.
743 let is_stream = fd_type == Stream
746 ioException (IOError Nothing InappropriateType "openFile"
747 "is a directory" Nothing)
750 | ReadWriteHandle <- ha_type -> mkDuplexHandle fd is_stream filepath binary
751 | otherwise -> mkFileHandle fd is_stream filepath ha_type binary
753 -- regular files need to be locked
755 r <- lockFile (fromIntegral fd) (fromBool write) 1{-exclusive-}
757 ioException (IOError Nothing ResourceBusy "openFile"
758 "file is locked" Nothing)
760 -- truncate the file if necessary
761 when truncate (fileTruncate filepath)
763 mkFileHandle fd is_stream filepath ha_type binary
766 fdToHandle :: FD -> IO Handle
769 let fd_str = "<file descriptor: " ++ show fd ++ ">"
770 openFd fd Nothing fd_str mode True{-bin mode-} False{-no truncate-}
772 foreign import ccall unsafe "lockFile"
773 lockFile :: CInt -> CInt -> CInt -> IO CInt
775 foreign import ccall unsafe "unlockFile"
776 unlockFile :: CInt -> IO CInt
778 mkStdHandle :: FD -> FilePath -> HandleType -> IORef Buffer -> BufferMode
780 mkStdHandle fd filepath ha_type buf bmode = do
781 spares <- newIORef BufferListNil
782 newFileHandle stdHandleFinalizer
783 (Handle__ { haFD = fd,
785 haIsBin = dEFAULT_OPEN_IN_BINARY_MODE,
787 haBufferMode = bmode,
788 haFilePath = filepath,
791 haOtherSide = Nothing
794 mkFileHandle :: FD -> Bool -> FilePath -> HandleType -> Bool -> IO Handle
795 mkFileHandle fd is_stream filepath ha_type binary = do
796 (buf, bmode) <- getBuffer fd (initBufferState ha_type)
797 spares <- newIORef BufferListNil
798 newFileHandle handleFinalizer
799 (Handle__ { haFD = fd,
802 haIsStream = is_stream,
803 haBufferMode = bmode,
804 haFilePath = filepath,
807 haOtherSide = Nothing
810 mkDuplexHandle :: FD -> Bool -> FilePath -> Bool -> IO Handle
811 mkDuplexHandle fd is_stream filepath binary = do
812 (w_buf, w_bmode) <- getBuffer fd WriteBuffer
813 w_spares <- newIORef BufferListNil
815 Handle__ { haFD = fd,
816 haType = WriteHandle,
818 haIsStream = is_stream,
819 haBufferMode = w_bmode,
820 haFilePath = filepath,
822 haBuffers = w_spares,
823 haOtherSide = Nothing
825 write_side <- newMVar w_handle_
827 (r_buf, r_bmode) <- getBuffer fd ReadBuffer
828 r_spares <- newIORef BufferListNil
830 Handle__ { haFD = fd,
833 haIsStream = is_stream,
834 haBufferMode = r_bmode,
835 haFilePath = filepath,
837 haBuffers = r_spares,
838 haOtherSide = Just write_side
840 read_side <- newMVar r_handle_
842 addMVarFinalizer read_side (handleFinalizer read_side)
843 return (DuplexHandle read_side write_side)
846 initBufferState ReadHandle = ReadBuffer
847 initBufferState _ = WriteBuffer
849 -- ---------------------------------------------------------------------------
852 -- Computation `hClose hdl' makes handle `hdl' closed. Before the
853 -- computation finishes, any items buffered for output and not already
854 -- sent to the operating system are flushed as for `hFlush'.
856 -- For a duplex handle, we close&flush the write side, and just close
859 hClose :: Handle -> IO ()
860 hClose h@(FileHandle m) = hClose' h m
861 hClose h@(DuplexHandle r w) = hClose' h w >> hClose' h r
863 hClose' h m = withHandle__' "hClose" h m $ hClose_help
865 -- hClose_help is also called by lazyRead (in PrelIO) when EOF is read
866 -- or an IO error occurs on a lazy stream. The semi-closed Handle is
867 -- then closed immediately. We have to be careful with DuplexHandles
868 -- though: we have to leave the closing to the finalizer in that case,
869 -- because the write side may still be in use.
870 hClose_help :: Handle__ -> IO Handle__
871 hClose_help handle_ =
872 case haType handle_ of
873 ClosedHandle -> return handle_
875 let fd = haFD handle_
876 c_fd = fromIntegral fd
878 flushWriteBufferOnly handle_
880 -- close the file descriptor, but not when this is the read
881 -- side of a duplex handle, and not when this is one of the
883 case haOtherSide handle_ of
885 when (fd /= fd_stdin && fd /= fd_stdout && fd /= fd_stderr) $
886 throwErrnoIfMinus1Retry_ "hClose"
887 #ifdef mingw32_TARGET_OS
888 (closeFd (haIsStream handle_) c_fd)
894 -- free the spare buffers
895 writeIORef (haBuffers handle_) BufferListNil
900 -- we must set the fd to -1, because the finalizer is going
901 -- to run eventually and try to close/unlock it.
902 return (handle_{ haFD = -1,
903 haType = ClosedHandle
906 -----------------------------------------------------------------------------
907 -- Detecting the size of a file
909 -- For a handle `hdl' which attached to a physical file, `hFileSize
910 -- hdl' returns the size of `hdl' in terms of the number of items
911 -- which can be read from `hdl'.
913 hFileSize :: Handle -> IO Integer
915 withHandle_ "hFileSize" handle $ \ handle_ -> do
916 case haType handle_ of
917 ClosedHandle -> ioe_closedHandle
918 SemiClosedHandle -> ioe_closedHandle
919 _ -> do flushWriteBufferOnly handle_
920 r <- fdFileSize (haFD handle_)
923 else ioException (IOError Nothing InappropriateType "hFileSize"
924 "not a regular file" Nothing)
926 -- ---------------------------------------------------------------------------
927 -- Detecting the End of Input
929 -- For a readable handle `hdl', `hIsEOF hdl' returns
930 -- `True' if no further input can be taken from `hdl' or for a
931 -- physical file, if the current I/O position is equal to the length of
932 -- the file. Otherwise, it returns `False'.
934 hIsEOF :: Handle -> IO Bool
937 (do hLookAhead handle; return False)
938 (\e -> if isEOFError e then return True else ioError e)
943 -- ---------------------------------------------------------------------------
946 -- hLookahead returns the next character from the handle without
947 -- removing it from the input buffer, blocking until a character is
950 hLookAhead :: Handle -> IO Char
951 hLookAhead handle = do
952 wantReadableHandle "hLookAhead" handle $ \handle_ -> do
953 let ref = haBuffer handle_
955 is_line = haBufferMode handle_ == LineBuffering
958 -- fill up the read buffer if necessary
959 new_buf <- if bufferEmpty buf
960 then fillReadBuffer fd is_line (haIsStream handle_) buf
963 writeIORef ref new_buf
965 (c,_) <- readCharFromBuffer (bufBuf buf) (bufRPtr buf)
968 -- ---------------------------------------------------------------------------
969 -- Buffering Operations
971 -- Three kinds of buffering are supported: line-buffering,
972 -- block-buffering or no-buffering. See GHC.IOBase for definition and
973 -- further explanation of what the type represent.
975 -- Computation `hSetBuffering hdl mode' sets the mode of buffering for
976 -- handle hdl on subsequent reads and writes.
978 -- * If mode is LineBuffering, line-buffering should be enabled if possible.
980 -- * If mode is `BlockBuffering size', then block-buffering
981 -- should be enabled if possible. The size of the buffer is n items
982 -- if size is `Just n' and is otherwise implementation-dependent.
984 -- * If mode is NoBuffering, then buffering is disabled if possible.
986 -- If the buffer mode is changed from BlockBuffering or
987 -- LineBuffering to NoBuffering, then any items in the output
988 -- buffer are written to the device, and any items in the input buffer
989 -- are discarded. The default buffering mode when a handle is opened
990 -- is implementation-dependent and may depend on the object which is
991 -- attached to that handle.
993 hSetBuffering :: Handle -> BufferMode -> IO ()
994 hSetBuffering handle mode =
995 withAllHandles__ "hSetBuffering" handle $ \ handle_ -> do
996 case haType handle_ of
997 ClosedHandle -> ioe_closedHandle
1000 - we flush the old buffer regardless of whether
1001 the new buffer could fit the contents of the old buffer
1003 - allow a handle's buffering to change even if IO has
1004 occurred (ANSI C spec. does not allow this, nor did
1005 the previous implementation of IO.hSetBuffering).
1006 - a non-standard extension is to allow the buffering
1007 of semi-closed handles to change [sof 6/98]
1011 let state = initBufferState (haType handle_)
1014 -- we always have a 1-character read buffer for
1015 -- unbuffered handles: it's needed to
1016 -- support hLookAhead.
1017 NoBuffering -> allocateBuffer 1 ReadBuffer
1018 LineBuffering -> allocateBuffer dEFAULT_BUFFER_SIZE state
1019 BlockBuffering Nothing -> allocateBuffer dEFAULT_BUFFER_SIZE state
1020 BlockBuffering (Just n) | n <= 0 -> ioe_bufsiz n
1021 | otherwise -> allocateBuffer n state
1022 writeIORef (haBuffer handle_) new_buf
1024 -- for input terminals we need to put the terminal into
1025 -- cooked or raw mode depending on the type of buffering.
1026 is_tty <- fdIsTTY (haFD handle_)
1027 when (is_tty && isReadableHandleType (haType handle_)) $
1029 #ifndef mingw32_TARGET_OS
1030 -- 'raw' mode under win32 is a bit too specialised (and troublesome
1031 -- for most common uses), so simply disable its use here.
1032 NoBuffering -> setCooked (haFD handle_) False
1034 _ -> setCooked (haFD handle_) True
1036 -- throw away spare buffers, they might be the wrong size
1037 writeIORef (haBuffers handle_) BufferListNil
1039 return (handle_{ haBufferMode = mode })
1041 -- -----------------------------------------------------------------------------
1044 -- The action `hFlush hdl' causes any items buffered for output
1045 -- in handle `hdl' to be sent immediately to the operating
1048 hFlush :: Handle -> IO ()
1050 wantWritableHandle "hFlush" handle $ \ handle_ -> do
1051 buf <- readIORef (haBuffer handle_)
1052 if bufferIsWritable buf && not (bufferEmpty buf)
1053 then do flushed_buf <- flushWriteBuffer (haFD handle_) (haIsStream handle_) buf
1054 writeIORef (haBuffer handle_) flushed_buf
1058 -- -----------------------------------------------------------------------------
1059 -- Repositioning Handles
1061 data HandlePosn = HandlePosn Handle HandlePosition
1063 instance Eq HandlePosn where
1064 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
1066 instance Show HandlePosn where
1067 showsPrec p (HandlePosn h pos) =
1068 showsPrec p h . showString " at position " . shows pos
1070 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
1071 -- We represent it as an Integer on the Haskell side, but
1072 -- cheat slightly in that hGetPosn calls upon a C helper
1073 -- that reports the position back via (merely) an Int.
1074 type HandlePosition = Integer
1076 -- Computation `hGetPosn hdl' returns the current I/O position of
1077 -- `hdl' as an abstract position. Computation `hSetPosn p' sets the
1078 -- position of `hdl' to a previously obtained position `p'.
1080 hGetPosn :: Handle -> IO HandlePosn
1081 hGetPosn handle = do
1082 posn <- hTell handle
1083 return (HandlePosn handle posn)
1085 hSetPosn :: HandlePosn -> IO ()
1086 hSetPosn (HandlePosn h i) = hSeek h AbsoluteSeek i
1088 -- ---------------------------------------------------------------------------
1092 The action `hSeek hdl mode i' sets the position of handle
1093 `hdl' depending on `mode'. If `mode' is
1095 * AbsoluteSeek - The position of `hdl' is set to `i'.
1096 * RelativeSeek - The position of `hdl' is set to offset `i' from
1097 the current position.
1098 * SeekFromEnd - The position of `hdl' is set to offset `i' from
1099 the end of the file.
1101 Some handles may not be seekable (see `hIsSeekable'), or only
1102 support a subset of the possible positioning operations (e.g. it may
1103 only be possible to seek to the end of a tape, or to a positive
1104 offset from the beginning or current position).
1106 It is not possible to set a negative I/O position, or for a physical
1107 file, an I/O position beyond the current end-of-file.
1110 - when seeking using `SeekFromEnd', positive offsets (>=0) means
1111 seeking at or past EOF.
1113 - we possibly deviate from the report on the issue of seeking within
1114 the buffer and whether to flush it or not. The report isn't exactly
1118 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
1119 deriving (Eq, Ord, Ix, Enum, Read, Show)
1121 hSeek :: Handle -> SeekMode -> Integer -> IO ()
1122 hSeek handle mode offset =
1123 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
1125 puts ("hSeek " ++ show (mode,offset) ++ "\n")
1127 let ref = haBuffer handle_
1128 buf <- readIORef ref
1134 throwErrnoIfMinus1Retry_ "hSeek"
1135 (c_lseek (fromIntegral (haFD handle_)) (fromIntegral offset) whence)
1138 whence = case mode of
1139 AbsoluteSeek -> sEEK_SET
1140 RelativeSeek -> sEEK_CUR
1141 SeekFromEnd -> sEEK_END
1143 if bufferIsWritable buf
1144 then do new_buf <- flushWriteBuffer fd (haIsStream handle_) buf
1145 writeIORef ref new_buf
1149 if mode == RelativeSeek && offset >= 0 && offset < fromIntegral (w - r)
1150 then writeIORef ref buf{ bufRPtr = r + fromIntegral offset }
1153 new_buf <- flushReadBuffer (haFD handle_) buf
1154 writeIORef ref new_buf
1158 hTell :: Handle -> IO Integer
1160 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
1162 #if defined(mingw32_TARGET_OS)
1163 -- urgh, on Windows we have to worry about \n -> \r\n translation,
1164 -- so we can't easily calculate the file position using the
1165 -- current buffer size. Just flush instead.
1168 let fd = fromIntegral (haFD handle_)
1169 posn <- fromIntegral `liftM`
1170 throwErrnoIfMinus1Retry "hGetPosn"
1171 (c_lseek fd 0 sEEK_CUR)
1173 let ref = haBuffer handle_
1174 buf <- readIORef ref
1177 | bufferIsWritable buf = posn + fromIntegral (bufWPtr buf)
1178 | otherwise = posn - fromIntegral (bufWPtr buf - bufRPtr buf)
1180 puts ("\nhGetPosn: (fd, posn, real_posn) = " ++ show (fd, posn, real_posn) ++ "\n")
1181 puts (" (bufWPtr, bufRPtr) = " ++ show (bufWPtr buf, bufRPtr buf) ++ "\n")
1185 -- -----------------------------------------------------------------------------
1186 -- Handle Properties
1188 -- A number of operations return information about the properties of a
1189 -- handle. Each of these operations returns `True' if the handle has
1190 -- the specified property, and `False' otherwise.
1192 hIsOpen :: Handle -> IO Bool
1194 withHandle_ "hIsOpen" handle $ \ handle_ -> do
1195 case haType handle_ of
1196 ClosedHandle -> return False
1197 SemiClosedHandle -> return False
1200 hIsClosed :: Handle -> IO Bool
1202 withHandle_ "hIsClosed" handle $ \ handle_ -> do
1203 case haType handle_ of
1204 ClosedHandle -> return True
1207 {- not defined, nor exported, but mentioned
1208 here for documentation purposes:
1210 hSemiClosed :: Handle -> IO Bool
1214 return (not (ho || hc))
1217 hIsReadable :: Handle -> IO Bool
1218 hIsReadable (DuplexHandle _ _) = return True
1219 hIsReadable handle =
1220 withHandle_ "hIsReadable" handle $ \ handle_ -> do
1221 case haType handle_ of
1222 ClosedHandle -> ioe_closedHandle
1223 SemiClosedHandle -> ioe_closedHandle
1224 htype -> return (isReadableHandleType htype)
1226 hIsWritable :: Handle -> IO Bool
1227 hIsWritable (DuplexHandle _ _) = return False
1228 hIsWritable handle =
1229 withHandle_ "hIsWritable" handle $ \ handle_ -> do
1230 case haType handle_ of
1231 ClosedHandle -> ioe_closedHandle
1232 SemiClosedHandle -> ioe_closedHandle
1233 htype -> return (isWritableHandleType htype)
1235 -- Querying how a handle buffers its data:
1237 hGetBuffering :: Handle -> IO BufferMode
1238 hGetBuffering handle =
1239 withHandle_ "hGetBuffering" handle $ \ handle_ -> do
1240 case haType handle_ of
1241 ClosedHandle -> ioe_closedHandle
1243 -- We're being non-standard here, and allow the buffering
1244 -- of a semi-closed handle to be queried. -- sof 6/98
1245 return (haBufferMode handle_) -- could be stricter..
1247 hIsSeekable :: Handle -> IO Bool
1248 hIsSeekable handle =
1249 withHandle_ "hIsSeekable" handle $ \ handle_ -> do
1250 case haType handle_ of
1251 ClosedHandle -> ioe_closedHandle
1252 SemiClosedHandle -> ioe_closedHandle
1253 AppendHandle -> return False
1254 _ -> do t <- fdType (haFD handle_)
1255 return (t == RegularFile
1257 || tEXT_MODE_SEEK_ALLOWED))
1259 -- -----------------------------------------------------------------------------
1260 -- Changing echo status
1262 -- Non-standard GHC extension is to allow the echoing status
1263 -- of a handles connected to terminals to be reconfigured:
1265 hSetEcho :: Handle -> Bool -> IO ()
1266 hSetEcho handle on = do
1267 isT <- hIsTerminalDevice handle
1271 withHandle_ "hSetEcho" handle $ \ handle_ -> do
1272 case haType handle_ of
1273 ClosedHandle -> ioe_closedHandle
1274 _ -> setEcho (haFD handle_) on
1276 hGetEcho :: Handle -> IO Bool
1277 hGetEcho handle = do
1278 isT <- hIsTerminalDevice handle
1282 withHandle_ "hGetEcho" handle $ \ handle_ -> do
1283 case haType handle_ of
1284 ClosedHandle -> ioe_closedHandle
1285 _ -> getEcho (haFD handle_)
1287 hIsTerminalDevice :: Handle -> IO Bool
1288 hIsTerminalDevice handle = do
1289 withHandle_ "hIsTerminalDevice" handle $ \ handle_ -> do
1290 case haType handle_ of
1291 ClosedHandle -> ioe_closedHandle
1292 _ -> fdIsTTY (haFD handle_)
1294 -- -----------------------------------------------------------------------------
1297 -- | On Windows, reading a file in text mode (which is the default) will
1298 -- translate CRLF to LF, and writing will translate LF to CRLF. This
1299 -- is usually what you want with text files. With binary files this is
1300 -- undesirable; also, as usual under Microsoft operating systems, text
1301 -- mode treats control-Z as EOF. Setting binary mode using
1302 -- 'hSetBinaryMode' turns off all special treatment of end-of-line and
1303 -- end-of-file characters.
1305 hSetBinaryMode :: Handle -> Bool -> IO ()
1306 hSetBinaryMode handle bin =
1307 withAllHandles__ "hSetBinaryMode" handle $ \ handle_ ->
1308 do throwErrnoIfMinus1_ "hSetBinaryMode"
1309 (setmode (fromIntegral (haFD handle_)) bin)
1310 return handle_{haIsBin=bin}
1312 foreign import ccall unsafe "__hscore_setmode"
1313 setmode :: CInt -> Bool -> IO CInt
1315 -- -----------------------------------------------------------------------------
1316 -- Duplicating a Handle
1318 -- |Returns a duplicate of the original handle, with its own buffer
1319 -- and file pointer. The original handle's buffer is flushed, including
1320 -- discarding any input data, before the handle is duplicated.
1322 hDuplicate :: Handle -> IO Handle
1323 hDuplicate h@(FileHandle m) = do
1324 new_h_ <- withHandle' "hDuplicate" h m (dupHandle_ Nothing)
1325 new_m <- newMVar new_h_
1326 return (FileHandle new_m)
1327 hDuplicate h@(DuplexHandle r w) = do
1328 new_w_ <- withHandle' "hDuplicate" h w (dupHandle_ Nothing)
1329 new_w <- newMVar new_w_
1330 new_r_ <- withHandle' "hDuplicate" h r (dupHandle_ (Just new_w))
1331 new_r <- newMVar new_r_
1332 return (DuplexHandle new_r new_w)
1334 dupHandle_ other_side h_ = do
1335 -- flush the buffer first, so we don't have to copy its contents
1337 new_fd <- c_dup (fromIntegral (haFD h_))
1338 buffer <- allocateBuffer dEFAULT_BUFFER_SIZE (initBufferState (haType h_))
1339 ioref <- newIORef buffer
1340 ioref_buffers <- newIORef BufferListNil
1342 let new_handle_ = h_{ haFD = fromIntegral new_fd,
1344 haBuffers = ioref_buffers,
1345 haOtherSide = other_side }
1346 return (h_, new_handle_)
1348 -- -----------------------------------------------------------------------------
1349 -- Replacing a Handle
1352 Makes the second handle a duplicate of the first handle. The second
1353 handle will be closed first, if it is not already.
1355 This can be used to retarget the standard Handles, for example:
1357 > do h <- openFile "mystdout" WriteMode
1358 > hDuplicateTo h stdout
1361 hDuplicateTo :: Handle -> Handle -> IO ()
1362 hDuplicateTo h1@(FileHandle m1) h2@(FileHandle m2) = do
1363 withHandle__' "hDuplicateTo" h2 m2 $ \h2_ -> do
1364 _ <- hClose_help h2_
1365 withHandle' "hDuplicateTo" h1 m1 (dupHandle_ Nothing)
1366 hDuplicateTo h1@(DuplexHandle r1 w1) h2@(DuplexHandle r2 w2) = do
1367 withHandle__' "hDuplicateTo" h2 w2 $ \w2_ -> do
1368 _ <- hClose_help w2_
1369 withHandle' "hDuplicateTo" h1 r1 (dupHandle_ Nothing)
1370 withHandle__' "hDuplicateTo" h2 r2 $ \r2_ -> do
1371 _ <- hClose_help r2_
1372 withHandle' "hDuplicateTo" h1 r1 (dupHandle_ (Just w1))
1374 ioException (IOError (Just h1) IllegalOperation "hDuplicateTo"
1375 "handles are incompatible" Nothing)
1377 -- ---------------------------------------------------------------------------
1381 puts :: String -> IO ()
1382 puts s = withCString s $ \cstr -> do write_rawBuffer 1 False cstr 0 (fromIntegral (length s))
1386 -- -----------------------------------------------------------------------------
1387 -- wrappers to platform-specific constants:
1389 foreign import ccall unsafe "__hscore_supportsTextMode"
1390 tEXT_MODE_SEEK_ALLOWED :: Bool
1392 foreign import ccall unsafe "__hscore_bufsiz" dEFAULT_BUFFER_SIZE :: Int
1393 foreign import ccall unsafe "__hscore_seek_cur" sEEK_CUR :: CInt
1394 foreign import ccall unsafe "__hscore_seek_set" sEEK_SET :: CInt
1395 foreign import ccall unsafe "__hscore_seek_end" sEEK_END :: CInt