[project @ 2002-07-16 22:42:28 by sof]
[ghc.git] / libraries / base / GHC / Handle.hs
1 {-# OPTIONS -fno-implicit-prelude -#include "HsBase.h" #-}
2
3 #undef DEBUG_DUMP
4 #undef DEBUG
5
6 -----------------------------------------------------------------------------
7 -- |
8 -- Module : GHC.Handle
9 -- Copyright : (c) The University of Glasgow, 1994-2001
10 -- License : see libraries/base/LICENSE
11 --
12 -- Maintainer : libraries@haskell.org
13 -- Stability : internal
14 -- Portability : non-portable
15 --
16 -- This module defines the basic operations on I\/O \"handles\".
17 --
18 -----------------------------------------------------------------------------
19
20 module GHC.Handle (
21 withHandle, withHandle', withHandle_,
22 wantWritableHandle, wantReadableHandle, wantSeekableHandle,
23
24 newEmptyBuffer, allocateBuffer, readCharFromBuffer, writeCharIntoBuffer,
25 flushWriteBufferOnly, flushWriteBuffer, flushReadBuffer, fillReadBuffer,
26 read_off, read_off_ba,
27 write_off, write_off_ba, unlockFile,
28
29 ioe_closedHandle, ioe_EOF, ioe_notReadable, ioe_notWritable,
30
31 stdin, stdout, stderr,
32 IOMode(..), IOModeEx(..), openFile, openFileEx, openFd,
33 hFileSize, hIsEOF, isEOF, hLookAhead, hSetBuffering, hSetBinaryMode,
34 hFlush,
35
36 hClose, hClose_help,
37
38 HandlePosn(..), hGetPosn, hSetPosn,
39 SeekMode(..), hSeek, hTell,
40
41 hIsOpen, hIsClosed, hIsReadable, hIsWritable, hGetBuffering, hIsSeekable,
42 hSetEcho, hGetEcho, hIsTerminalDevice,
43
44 #ifdef DEBUG_DUMP
45 puts,
46 #endif
47
48 ) where
49
50 import Control.Monad
51 import Data.Bits
52 import Data.Maybe
53 import Foreign
54 import Foreign.C
55 import System.IO.Error
56
57 import GHC.Posix
58 import GHC.Real
59
60 import GHC.Arr
61 import GHC.Base
62 import GHC.Read ( Read )
63 import GHC.List
64 import GHC.IOBase
65 import GHC.Exception
66 import GHC.Enum
67 import GHC.Num ( Integer(..), Num(..) )
68 import GHC.Show
69 import GHC.Real ( toInteger )
70
71 import GHC.Conc
72
73 -- -----------------------------------------------------------------------------
74 -- TODO:
75
76 -- hWaitForInput blocks (should use a timeout)
77
78 -- unbuffered hGetLine is a bit dodgy
79
80 -- hSetBuffering: can't change buffering on a stream,
81 -- when the read buffer is non-empty? (no way to flush the buffer)
82
83 -- ---------------------------------------------------------------------------
84 -- Are files opened by default in text or binary mode, if the user doesn't
85 -- specify?
86
87 dEFAULT_OPEN_IN_BINARY_MODE = False :: Bool
88
89 -- ---------------------------------------------------------------------------
90 -- Creating a new handle
91
92 newFileHandle :: (MVar Handle__ -> IO ()) -> Handle__ -> IO Handle
93 newFileHandle finalizer hc = do
94 m <- newMVar hc
95 addMVarFinalizer m (finalizer m)
96 return (FileHandle m)
97
98 -- ---------------------------------------------------------------------------
99 -- Working with Handles
100
101 {-
102 In the concurrent world, handles are locked during use. This is done
103 by wrapping an MVar around the handle which acts as a mutex over
104 operations on the handle.
105
106 To avoid races, we use the following bracketing operations. The idea
107 is to obtain the lock, do some operation and replace the lock again,
108 whether the operation succeeded or failed. We also want to handle the
109 case where the thread receives an exception while processing the IO
110 operation: in these cases we also want to relinquish the lock.
111
112 There are three versions of @withHandle@: corresponding to the three
113 possible combinations of:
114
115 - the operation may side-effect the handle
116 - the operation may return a result
117
118 If the operation generates an error or an exception is raised, the
119 original handle is always replaced [ this is the case at the moment,
120 but we might want to revisit this in the future --SDM ].
121 -}
122
123 {-# INLINE withHandle #-}
124 withHandle :: String -> Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
125 withHandle fun h@(FileHandle m) act = withHandle' fun h m act
126 withHandle fun h@(DuplexHandle m _) act = withHandle' fun h m act
127
128 withHandle' :: String -> Handle -> MVar Handle__
129 -> (Handle__ -> IO (Handle__,a)) -> IO a
130 withHandle' fun h m act =
131 block $ do
132 h_ <- takeMVar m
133 checkBufferInvariants h_
134 (h',v) <- catchException (act h_)
135 (\ ex -> putMVar m h_ >> throw (augmentIOError ex fun h h_))
136 checkBufferInvariants h'
137 putMVar m h'
138 return v
139
140 {-# INLINE withHandle_ #-}
141 withHandle_ :: String -> Handle -> (Handle__ -> IO a) -> IO a
142 withHandle_ fun h@(FileHandle m) act = withHandle_' fun h m act
143 withHandle_ fun h@(DuplexHandle m _) act = withHandle_' fun h m act
144
145 withHandle_' fun h m act =
146 block $ do
147 h_ <- takeMVar m
148 checkBufferInvariants h_
149 v <- catchException (act h_)
150 (\ ex -> putMVar m h_ >> throw (augmentIOError ex fun h h_))
151 checkBufferInvariants h_
152 putMVar m h_
153 return v
154
155 withAllHandles__ :: String -> Handle -> (Handle__ -> IO Handle__) -> IO ()
156 withAllHandles__ fun h@(FileHandle m) act = withHandle__' fun h m act
157 withAllHandles__ fun h@(DuplexHandle r w) act = do
158 withHandle__' fun h r act
159 withHandle__' fun h w act
160
161 withHandle__' fun h m act =
162 block $ do
163 h_ <- takeMVar m
164 checkBufferInvariants h_
165 h' <- catchException (act h_)
166 (\ ex -> putMVar m h_ >> throw (augmentIOError ex fun h h_))
167 checkBufferInvariants h'
168 putMVar m h'
169 return ()
170
171 augmentIOError (IOException (IOError _ iot _ str fp)) fun h h_
172 = IOException (IOError (Just h) iot fun str filepath)
173 where filepath | Just _ <- fp = fp
174 | otherwise = Just (haFilePath h_)
175 augmentIOError other_exception _ _ _
176 = other_exception
177
178 -- ---------------------------------------------------------------------------
179 -- Wrapper for write operations.
180
181 wantWritableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
182 wantWritableHandle fun h@(FileHandle m) act
183 = wantWritableHandle' fun h m act
184 wantWritableHandle fun h@(DuplexHandle _ m) act
185 = wantWritableHandle' fun h m act
186 -- ToDo: in the Duplex case, we don't need to checkWritableHandle
187
188 wantWritableHandle'
189 :: String -> Handle -> MVar Handle__
190 -> (Handle__ -> IO a) -> IO a
191 wantWritableHandle' fun h m act
192 = withHandle_' fun h m (checkWritableHandle act)
193
194 checkWritableHandle act handle_
195 = case haType handle_ of
196 ClosedHandle -> ioe_closedHandle
197 SemiClosedHandle -> ioe_closedHandle
198 ReadHandle -> ioe_notWritable
199 ReadWriteHandle -> do
200 let ref = haBuffer handle_
201 buf <- readIORef ref
202 new_buf <-
203 if not (bufferIsWritable buf)
204 then do b <- flushReadBuffer (haFD handle_) buf
205 return b{ bufState=WriteBuffer }
206 else return buf
207 writeIORef ref new_buf
208 act handle_
209 _other -> act handle_
210
211 -- ---------------------------------------------------------------------------
212 -- Wrapper for read operations.
213
214 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
215 wantReadableHandle fun h@(FileHandle m) act
216 = wantReadableHandle' fun h m act
217 wantReadableHandle fun h@(DuplexHandle m _) act
218 = wantReadableHandle' fun h m act
219 -- ToDo: in the Duplex case, we don't need to checkReadableHandle
220
221 wantReadableHandle'
222 :: String -> Handle -> MVar Handle__
223 -> (Handle__ -> IO a) -> IO a
224 wantReadableHandle' fun h m act
225 = withHandle_' fun h m (checkReadableHandle act)
226
227 checkReadableHandle act handle_ =
228 case haType handle_ of
229 ClosedHandle -> ioe_closedHandle
230 SemiClosedHandle -> ioe_closedHandle
231 AppendHandle -> ioe_notReadable
232 WriteHandle -> ioe_notReadable
233 ReadWriteHandle -> do
234 let ref = haBuffer handle_
235 buf <- readIORef ref
236 when (bufferIsWritable buf) $ do
237 new_buf <- flushWriteBuffer (haFD handle_) (haIsStream handle_) buf
238 writeIORef ref new_buf{ bufState=ReadBuffer }
239 act handle_
240 _other -> act handle_
241
242 -- ---------------------------------------------------------------------------
243 -- Wrapper for seek operations.
244
245 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
246 wantSeekableHandle fun h@(DuplexHandle _ _) _act =
247 ioException (IOError (Just h) IllegalOperation fun
248 "handle is not seekable" Nothing)
249 wantSeekableHandle fun h@(FileHandle m) act =
250 withHandle_' fun h m (checkSeekableHandle act)
251
252 checkSeekableHandle act handle_ =
253 case haType handle_ of
254 ClosedHandle -> ioe_closedHandle
255 SemiClosedHandle -> ioe_closedHandle
256 AppendHandle -> ioe_notSeekable
257 _ | haIsBin handle_ || tEXT_MODE_SEEK_ALLOWED -> act handle_
258 | otherwise -> ioe_notSeekable_notBin
259
260 -- -----------------------------------------------------------------------------
261 -- Handy IOErrors
262
263 ioe_closedHandle, ioe_EOF,
264 ioe_notReadable, ioe_notWritable,
265 ioe_notSeekable, ioe_notSeekable_notBin :: IO a
266
267 ioe_closedHandle = ioException
268 (IOError Nothing IllegalOperation ""
269 "handle is closed" Nothing)
270 ioe_EOF = ioException
271 (IOError Nothing EOF "" "" Nothing)
272 ioe_notReadable = ioException
273 (IOError Nothing IllegalOperation ""
274 "handle is not open for reading" Nothing)
275 ioe_notWritable = ioException
276 (IOError Nothing IllegalOperation ""
277 "handle is not open for writing" Nothing)
278 ioe_notSeekable = ioException
279 (IOError Nothing IllegalOperation ""
280 "handle is not seekable" Nothing)
281 ioe_notSeekable_notBin = ioException
282 (IOError Nothing IllegalOperation ""
283 "seek operations on text-mode handles are not allowed on this platform"
284 Nothing)
285
286 ioe_bufsiz :: Int -> IO a
287 ioe_bufsiz n = ioException
288 (IOError Nothing InvalidArgument "hSetBuffering"
289 ("illegal buffer size " ++ showsPrec 9 n []) Nothing)
290 -- 9 => should be parens'ified.
291
292 -- -----------------------------------------------------------------------------
293 -- Handle Finalizers
294
295 -- For a duplex handle, we arrange that the read side points to the write side
296 -- (and hence keeps it alive if the read side is alive). This is done by
297 -- having the haOtherSide field of the read side point to the read side.
298 -- The finalizer is then placed on the write side, and the handle only gets
299 -- finalized once, when both sides are no longer required.
300
301 stdHandleFinalizer :: MVar Handle__ -> IO ()
302 stdHandleFinalizer m = do
303 h_ <- takeMVar m
304 flushWriteBufferOnly h_
305
306 handleFinalizer :: MVar Handle__ -> IO ()
307 handleFinalizer m = do
308 h_ <- takeMVar m
309 let
310 -- hClose puts both the fd and the handle's type
311 -- into a closed state, so it's a bit excessive
312 -- to test for both here, but caution sometimes
313 -- pays off..
314 alreadyClosed =
315 case haType h_ of { ClosedHandle{} -> True; _ -> False }
316 fd = fromIntegral (haFD h_)
317
318 when (not alreadyClosed && fd /= -1) $ do
319 flushWriteBufferOnly h_
320 unlockFile fd
321 #ifdef mingw32_TARGET_OS
322 (closeFd (haIsStream h_) fd >> return ())
323 #else
324 (c_close fd >> return ())
325 #endif
326
327 -- ---------------------------------------------------------------------------
328 -- Grimy buffer operations
329
330 #ifdef DEBUG
331 checkBufferInvariants h_ = do
332 let ref = haBuffer h_
333 Buffer{ bufWPtr=w, bufRPtr=r, bufSize=size, bufState=state } <- readIORef ref
334 if not (
335 size > 0
336 && r <= w
337 && w <= size
338 && ( r /= w || (r == 0 && w == 0) )
339 && ( state /= WriteBuffer || r == 0 )
340 && ( state /= WriteBuffer || w < size ) -- write buffer is never full
341 )
342 then error "buffer invariant violation"
343 else return ()
344 #else
345 checkBufferInvariants h_ = return ()
346 #endif
347
348 newEmptyBuffer :: RawBuffer -> BufferState -> Int -> Buffer
349 newEmptyBuffer b state size
350 = Buffer{ bufBuf=b, bufRPtr=0, bufWPtr=0, bufSize=size, bufState=state }
351
352 allocateBuffer :: Int -> BufferState -> IO Buffer
353 allocateBuffer sz@(I# size) state = IO $ \s ->
354 case newByteArray# size s of { (# s, b #) ->
355 (# s, newEmptyBuffer b state sz #) }
356
357 writeCharIntoBuffer :: RawBuffer -> Int -> Char -> IO Int
358 writeCharIntoBuffer slab (I# off) (C# c)
359 = IO $ \s -> case writeCharArray# slab off c s of
360 s -> (# s, I# (off +# 1#) #)
361
362 readCharFromBuffer :: RawBuffer -> Int -> IO (Char, Int)
363 readCharFromBuffer slab (I# off)
364 = IO $ \s -> case readCharArray# slab off s of
365 (# s, c #) -> (# s, (C# c, I# (off +# 1#)) #)
366
367 getBuffer :: FD -> BufferState -> IO (IORef Buffer, BufferMode)
368 getBuffer fd state = do
369 buffer <- allocateBuffer dEFAULT_BUFFER_SIZE state
370 ioref <- newIORef buffer
371 is_tty <- fdIsTTY fd
372
373 let buffer_mode
374 | is_tty = LineBuffering
375 | otherwise = BlockBuffering Nothing
376
377 return (ioref, buffer_mode)
378
379 mkUnBuffer :: IO (IORef Buffer)
380 mkUnBuffer = do
381 buffer <- allocateBuffer 1 ReadBuffer
382 newIORef buffer
383
384 -- flushWriteBufferOnly flushes the buffer iff it contains pending write data.
385 flushWriteBufferOnly :: Handle__ -> IO ()
386 flushWriteBufferOnly h_ = do
387 let fd = haFD h_
388 ref = haBuffer h_
389 buf <- readIORef ref
390 new_buf <- if bufferIsWritable buf
391 then flushWriteBuffer fd (haIsStream h_) buf
392 else return buf
393 writeIORef ref new_buf
394
395 -- flushBuffer syncs the file with the buffer, including moving the
396 -- file pointer backwards in the case of a read buffer.
397 flushBuffer :: Handle__ -> IO ()
398 flushBuffer h_ = do
399 let ref = haBuffer h_
400 buf <- readIORef ref
401
402 flushed_buf <-
403 case bufState buf of
404 ReadBuffer -> flushReadBuffer (haFD h_) buf
405 WriteBuffer -> flushWriteBuffer (haFD h_) (haIsStream h_) buf
406
407 writeIORef ref flushed_buf
408
409 -- When flushing a read buffer, we seek backwards by the number of
410 -- characters in the buffer. The file descriptor must therefore be
411 -- seekable: attempting to flush the read buffer on an unseekable
412 -- handle is not allowed.
413
414 flushReadBuffer :: FD -> Buffer -> IO Buffer
415 flushReadBuffer fd buf
416 | bufferEmpty buf = return buf
417 | otherwise = do
418 let off = negate (bufWPtr buf - bufRPtr buf)
419 # ifdef DEBUG_DUMP
420 puts ("flushReadBuffer: new file offset = " ++ show off ++ "\n")
421 # endif
422 throwErrnoIfMinus1Retry "flushReadBuffer"
423 (c_lseek (fromIntegral fd) (fromIntegral off) sEEK_CUR)
424 return buf{ bufWPtr=0, bufRPtr=0 }
425
426 flushWriteBuffer :: FD -> Bool -> Buffer -> IO Buffer
427 flushWriteBuffer fd is_stream buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w } = do
428 let bytes = w - r
429 #ifdef DEBUG_DUMP
430 puts ("flushWriteBuffer, fd=" ++ show fd ++ ", bytes=" ++ show bytes ++ "\n")
431 #endif
432 if bytes == 0
433 then return (buf{ bufRPtr=0, bufWPtr=0 })
434 else do
435 res <- throwErrnoIfMinus1RetryMayBlock "flushWriteBuffer"
436 (write_off_ba (fromIntegral fd) is_stream b (fromIntegral r)
437 (fromIntegral bytes))
438 (threadWaitWrite fd)
439 let res' = fromIntegral res
440 if res' < bytes
441 then flushWriteBuffer fd is_stream (buf{ bufRPtr = r + res' })
442 else return buf{ bufRPtr=0, bufWPtr=0 }
443
444 foreign import ccall unsafe "__hscore_PrelHandle_write"
445 write_off_ba :: CInt -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
446
447 foreign import ccall unsafe "__hscore_PrelHandle_write"
448 write_off :: CInt -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
449
450 fillReadBuffer :: FD -> Bool -> Bool -> Buffer -> IO Buffer
451 fillReadBuffer fd is_line is_stream
452 buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w, bufSize=size } =
453 -- buffer better be empty:
454 assert (r == 0 && w == 0) $ do
455 fillReadBufferLoop fd is_line is_stream buf b w size
456
457 -- For a line buffer, we just get the first chunk of data to arrive,
458 -- and don't wait for the whole buffer to be full (but we *do* wait
459 -- until some data arrives). This isn't really line buffering, but it
460 -- appears to be what GHC has done for a long time, and I suspect it
461 -- is more useful than line buffering in most cases.
462
463 fillReadBufferLoop fd is_line is_stream buf b w size = do
464 let bytes = size - w
465 if bytes == 0 -- buffer full?
466 then return buf{ bufRPtr=0, bufWPtr=w }
467 else do
468 #ifdef DEBUG_DUMP
469 puts ("fillReadBufferLoop: bytes = " ++ show bytes ++ "\n")
470 #endif
471 res <- throwErrnoIfMinus1RetryMayBlock "fillReadBuffer"
472 (read_off_ba fd is_stream b (fromIntegral w) (fromIntegral bytes))
473 (threadWaitRead fd)
474 let res' = fromIntegral res
475 #ifdef DEBUG_DUMP
476 puts ("fillReadBufferLoop: res' = " ++ show res' ++ "\n")
477 #endif
478 if res' == 0
479 then if w == 0
480 then ioe_EOF
481 else return buf{ bufRPtr=0, bufWPtr=w }
482 else if res' < bytes && not is_line
483 then fillReadBufferLoop fd is_line is_stream buf b (w+res') size
484 else return buf{ bufRPtr=0, bufWPtr=w+res' }
485
486 foreign import ccall unsafe "__hscore_PrelHandle_read"
487 read_off_ba :: FD -> Bool -> RawBuffer -> Int -> CInt -> IO CInt
488
489 foreign import ccall unsafe "__hscore_PrelHandle_read"
490 read_off :: FD -> Bool -> Ptr CChar -> Int -> CInt -> IO CInt
491
492 -- ---------------------------------------------------------------------------
493 -- Standard Handles
494
495 -- Three handles are allocated during program initialisation. The first
496 -- two manage input or output from the Haskell program's standard input
497 -- or output channel respectively. The third manages output to the
498 -- standard error channel. These handles are initially open.
499
500 fd_stdin = 0 :: FD
501 fd_stdout = 1 :: FD
502 fd_stderr = 2 :: FD
503
504 stdin :: Handle
505 stdin = unsafePerformIO $ do
506 -- ToDo: acquire lock
507 setNonBlockingFD fd_stdin
508 (buf, bmode) <- getBuffer fd_stdin ReadBuffer
509 mkStdHandle fd_stdin "<stdin>" ReadHandle buf bmode
510
511 stdout :: Handle
512 stdout = unsafePerformIO $ do
513 -- ToDo: acquire lock
514 -- We don't set non-blocking mode on stdout or sterr, because
515 -- some shells don't recover properly.
516 -- setNonBlockingFD fd_stdout
517 (buf, bmode) <- getBuffer fd_stdout WriteBuffer
518 mkStdHandle fd_stdout "<stdout>" WriteHandle buf bmode
519
520 stderr :: Handle
521 stderr = unsafePerformIO $ do
522 -- ToDo: acquire lock
523 -- We don't set non-blocking mode on stdout or sterr, because
524 -- some shells don't recover properly.
525 -- setNonBlockingFD fd_stderr
526 buf <- mkUnBuffer
527 mkStdHandle fd_stderr "<stderr>" WriteHandle buf NoBuffering
528
529 -- ---------------------------------------------------------------------------
530 -- Opening and Closing Files
531
532 {-
533 Computation `openFile file mode' allocates and returns a new, open
534 handle to manage the file `file'. It manages input if `mode'
535 is `ReadMode', output if `mode' is `WriteMode' or `AppendMode',
536 and both input and output if mode is `ReadWriteMode'.
537
538 If the file does not exist and it is opened for output, it should be
539 created as a new file. If `mode' is `WriteMode' and the file
540 already exists, then it should be truncated to zero length. The
541 handle is positioned at the end of the file if `mode' is
542 `AppendMode', and otherwise at the beginning (in which case its
543 internal position is 0).
544
545 Implementations should enforce, locally to the Haskell process,
546 multiple-reader single-writer locking on files, which is to say that
547 there may either be many handles on the same file which manage input,
548 or just one handle on the file which manages output. If any open or
549 semi-closed handle is managing a file for output, no new handle can be
550 allocated for that file. If any open or semi-closed handle is
551 managing a file for input, new handles can only be allocated if they
552 do not manage output.
553
554 Two files are the same if they have the same absolute name. An
555 implementation is free to impose stricter conditions.
556 -}
557
558 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
559 deriving (Eq, Ord, Ix, Enum, Read, Show)
560
561 data IOModeEx
562 = BinaryMode IOMode
563 | TextMode IOMode
564 deriving (Eq, Read, Show)
565
566 addFilePathToIOError fun fp (IOException (IOError h iot _ str _))
567 = IOException (IOError h iot fun str (Just fp))
568 addFilePathToIOError _ _ other_exception
569 = other_exception
570
571 openFile :: FilePath -> IOMode -> IO Handle
572 openFile fp im =
573 catch
574 (openFile' fp (if dEFAULT_OPEN_IN_BINARY_MODE
575 then BinaryMode im
576 else TextMode im))
577 (\e -> throw (addFilePathToIOError "openFile" fp e))
578
579 openFileEx :: FilePath -> IOModeEx -> IO Handle
580 openFileEx fp m =
581 catch
582 (openFile' fp m)
583 (\e -> throw (addFilePathToIOError "openFileEx" fp e))
584
585
586 openFile' filepath ex_mode =
587 withCString filepath $ \ f ->
588
589 let
590 (mode, binary) =
591 case ex_mode of
592 BinaryMode bmo -> (bmo, True)
593 TextMode tmo -> (tmo, False)
594
595 oflags1 = case mode of
596 ReadMode -> read_flags
597 WriteMode -> write_flags
598 ReadWriteMode -> rw_flags
599 AppendMode -> append_flags
600
601 truncate | WriteMode <- mode = True
602 | otherwise = False
603
604 binary_flags
605 | binary = o_BINARY
606 | otherwise = 0
607
608 oflags = oflags1 .|. binary_flags
609 in do
610
611 -- the old implementation had a complicated series of three opens,
612 -- which is perhaps because we have to be careful not to open
613 -- directories. However, the man pages I've read say that open()
614 -- always returns EISDIR if the file is a directory and was opened
615 -- for writing, so I think we're ok with a single open() here...
616 fd <- fromIntegral `liftM`
617 throwErrnoIfMinus1Retry "openFile"
618 (c_open f (fromIntegral oflags) 0o666)
619
620 openFd fd Nothing filepath mode binary truncate
621 -- ASSERT: if we just created the file, then openFd won't fail
622 -- (so we don't need to worry about removing the newly created file
623 -- in the event of an error).
624
625
626 std_flags = o_NONBLOCK .|. o_NOCTTY
627 output_flags = std_flags .|. o_CREAT
628 read_flags = std_flags .|. o_RDONLY
629 write_flags = output_flags .|. o_WRONLY
630 rw_flags = output_flags .|. o_RDWR
631 append_flags = write_flags .|. o_APPEND
632
633 -- ---------------------------------------------------------------------------
634 -- openFd
635
636 openFd :: FD -> Maybe FDType -> FilePath -> IOMode -> Bool -> Bool -> IO Handle
637 openFd fd mb_fd_type filepath mode binary truncate = do
638 -- turn on non-blocking mode
639 setNonBlockingFD fd
640
641 let (ha_type, write) =
642 case mode of
643 ReadMode -> ( ReadHandle, False )
644 WriteMode -> ( WriteHandle, True )
645 ReadWriteMode -> ( ReadWriteHandle, True )
646 AppendMode -> ( AppendHandle, True )
647
648 -- open() won't tell us if it was a directory if we only opened for
649 -- reading, so check again.
650 fd_type <-
651 case mb_fd_type of
652 Just x -> return x
653 Nothing -> fdType fd
654 let is_stream = fd_type == Stream
655 case fd_type of
656 Directory ->
657 ioException (IOError Nothing InappropriateType "openFile"
658 "is a directory" Nothing)
659
660 Stream
661 | ReadWriteHandle <- ha_type -> mkDuplexHandle fd is_stream filepath binary
662 | otherwise -> mkFileHandle fd is_stream filepath ha_type binary
663
664 -- regular files need to be locked
665 RegularFile -> do
666 r <- lockFile (fromIntegral fd) (fromBool write) 1{-exclusive-}
667 when (r == -1) $
668 ioException (IOError Nothing ResourceBusy "openFile"
669 "file is locked" Nothing)
670
671 -- truncate the file if necessary
672 when truncate (fileTruncate filepath)
673
674 mkFileHandle fd is_stream filepath ha_type binary
675
676
677 foreign import ccall unsafe "lockFile"
678 lockFile :: CInt -> CInt -> CInt -> IO CInt
679
680 foreign import ccall unsafe "unlockFile"
681 unlockFile :: CInt -> IO CInt
682
683 mkStdHandle :: FD -> FilePath -> HandleType -> IORef Buffer -> BufferMode
684 -> IO Handle
685 mkStdHandle fd filepath ha_type buf bmode = do
686 spares <- newIORef BufferListNil
687 newFileHandle stdHandleFinalizer
688 (Handle__ { haFD = fd,
689 haType = ha_type,
690 haIsBin = dEFAULT_OPEN_IN_BINARY_MODE,
691 haIsStream = False,
692 haBufferMode = bmode,
693 haFilePath = filepath,
694 haBuffer = buf,
695 haBuffers = spares,
696 haOtherSide = Nothing
697 })
698
699 mkFileHandle :: FD -> Bool -> FilePath -> HandleType -> Bool -> IO Handle
700 mkFileHandle fd is_stream filepath ha_type binary = do
701 (buf, bmode) <- getBuffer fd (initBufferState ha_type)
702 spares <- newIORef BufferListNil
703 newFileHandle handleFinalizer
704 (Handle__ { haFD = fd,
705 haType = ha_type,
706 haIsBin = binary,
707 haIsStream = is_stream,
708 haBufferMode = bmode,
709 haFilePath = filepath,
710 haBuffer = buf,
711 haBuffers = spares,
712 haOtherSide = Nothing
713 })
714
715 mkDuplexHandle :: FD -> Bool -> FilePath -> Bool -> IO Handle
716 mkDuplexHandle fd is_stream filepath binary = do
717 (w_buf, w_bmode) <- getBuffer fd WriteBuffer
718 w_spares <- newIORef BufferListNil
719 let w_handle_ =
720 Handle__ { haFD = fd,
721 haType = WriteHandle,
722 haIsBin = binary,
723 haIsStream = is_stream,
724 haBufferMode = w_bmode,
725 haFilePath = filepath,
726 haBuffer = w_buf,
727 haBuffers = w_spares,
728 haOtherSide = Nothing
729 }
730 write_side <- newMVar w_handle_
731
732 (r_buf, r_bmode) <- getBuffer fd ReadBuffer
733 r_spares <- newIORef BufferListNil
734 let r_handle_ =
735 Handle__ { haFD = fd,
736 haType = ReadHandle,
737 haIsBin = binary,
738 haIsStream = is_stream,
739 haBufferMode = r_bmode,
740 haFilePath = filepath,
741 haBuffer = r_buf,
742 haBuffers = r_spares,
743 haOtherSide = Just write_side
744 }
745 read_side <- newMVar r_handle_
746
747 addMVarFinalizer read_side (handleFinalizer read_side)
748 return (DuplexHandle read_side write_side)
749
750
751 initBufferState ReadHandle = ReadBuffer
752 initBufferState _ = WriteBuffer
753
754 -- ---------------------------------------------------------------------------
755 -- Closing a handle
756
757 -- Computation `hClose hdl' makes handle `hdl' closed. Before the
758 -- computation finishes, any items buffered for output and not already
759 -- sent to the operating system are flushed as for `hFlush'.
760
761 -- For a duplex handle, we close&flush the write side, and just close
762 -- the read side.
763
764 hClose :: Handle -> IO ()
765 hClose h@(FileHandle m) = hClose' h m
766 hClose h@(DuplexHandle r w) = hClose' h w >> hClose' h r
767
768 hClose' h m = withHandle__' "hClose" h m $ hClose_help
769
770 -- hClose_help is also called by lazyRead (in PrelIO) when EOF is read
771 -- or an IO error occurs on a lazy stream. The semi-closed Handle is
772 -- then closed immediately. We have to be careful with DuplexHandles
773 -- though: we have to leave the closing to the finalizer in that case,
774 -- because the write side may still be in use.
775 hClose_help :: Handle__ -> IO Handle__
776 hClose_help handle_ =
777 case haType handle_ of
778 ClosedHandle -> return handle_
779 _ -> do
780 let fd = haFD handle_
781 c_fd = fromIntegral fd
782
783 flushWriteBufferOnly handle_
784
785 -- close the file descriptor, but not when this is the read
786 -- side of a duplex handle, and not when this is one of the
787 -- std file handles.
788 case haOtherSide handle_ of
789 Nothing ->
790 when (fd /= fd_stdin && fd /= fd_stdout && fd /= fd_stderr) $
791 throwErrnoIfMinus1Retry_ "hClose"
792 #ifdef mingw32_TARGET_OS
793 (closeFd (haIsStream handle_) c_fd)
794 #else
795 (c_close c_fd)
796 #endif
797 Just _ -> return ()
798
799 -- free the spare buffers
800 writeIORef (haBuffers handle_) BufferListNil
801
802 -- unlock it
803 unlockFile c_fd
804
805 -- we must set the fd to -1, because the finalizer is going
806 -- to run eventually and try to close/unlock it.
807 return (handle_{ haFD = -1,
808 haType = ClosedHandle
809 })
810
811 -----------------------------------------------------------------------------
812 -- Detecting the size of a file
813
814 -- For a handle `hdl' which attached to a physical file, `hFileSize
815 -- hdl' returns the size of `hdl' in terms of the number of items
816 -- which can be read from `hdl'.
817
818 hFileSize :: Handle -> IO Integer
819 hFileSize handle =
820 withHandle_ "hFileSize" handle $ \ handle_ -> do
821 case haType handle_ of
822 ClosedHandle -> ioe_closedHandle
823 SemiClosedHandle -> ioe_closedHandle
824 _ -> do flushWriteBufferOnly handle_
825 r <- fdFileSize (haFD handle_)
826 if r /= -1
827 then return r
828 else ioException (IOError Nothing InappropriateType "hFileSize"
829 "not a regular file" Nothing)
830
831 -- ---------------------------------------------------------------------------
832 -- Detecting the End of Input
833
834 -- For a readable handle `hdl', `hIsEOF hdl' returns
835 -- `True' if no further input can be taken from `hdl' or for a
836 -- physical file, if the current I/O position is equal to the length of
837 -- the file. Otherwise, it returns `False'.
838
839 hIsEOF :: Handle -> IO Bool
840 hIsEOF handle =
841 catch
842 (do hLookAhead handle; return False)
843 (\e -> if isEOFError e then return True else throw e)
844
845 isEOF :: IO Bool
846 isEOF = hIsEOF stdin
847
848 -- ---------------------------------------------------------------------------
849 -- Looking ahead
850
851 -- hLookahead returns the next character from the handle without
852 -- removing it from the input buffer, blocking until a character is
853 -- available.
854
855 hLookAhead :: Handle -> IO Char
856 hLookAhead handle = do
857 wantReadableHandle "hLookAhead" handle $ \handle_ -> do
858 let ref = haBuffer handle_
859 fd = haFD handle_
860 is_line = haBufferMode handle_ == LineBuffering
861 buf <- readIORef ref
862
863 -- fill up the read buffer if necessary
864 new_buf <- if bufferEmpty buf
865 then fillReadBuffer fd is_line (haIsStream handle_) buf
866 else return buf
867
868 writeIORef ref new_buf
869
870 (c,_) <- readCharFromBuffer (bufBuf buf) (bufRPtr buf)
871 return c
872
873 -- ---------------------------------------------------------------------------
874 -- Buffering Operations
875
876 -- Three kinds of buffering are supported: line-buffering,
877 -- block-buffering or no-buffering. See GHC.IOBase for definition and
878 -- further explanation of what the type represent.
879
880 -- Computation `hSetBuffering hdl mode' sets the mode of buffering for
881 -- handle hdl on subsequent reads and writes.
882 --
883 -- * If mode is LineBuffering, line-buffering should be enabled if possible.
884 --
885 -- * If mode is `BlockBuffering size', then block-buffering
886 -- should be enabled if possible. The size of the buffer is n items
887 -- if size is `Just n' and is otherwise implementation-dependent.
888 --
889 -- * If mode is NoBuffering, then buffering is disabled if possible.
890
891 -- If the buffer mode is changed from BlockBuffering or
892 -- LineBuffering to NoBuffering, then any items in the output
893 -- buffer are written to the device, and any items in the input buffer
894 -- are discarded. The default buffering mode when a handle is opened
895 -- is implementation-dependent and may depend on the object which is
896 -- attached to that handle.
897
898 hSetBuffering :: Handle -> BufferMode -> IO ()
899 hSetBuffering handle mode =
900 withAllHandles__ "hSetBuffering" handle $ \ handle_ -> do
901 case haType handle_ of
902 ClosedHandle -> ioe_closedHandle
903 _ -> do
904 {- Note:
905 - we flush the old buffer regardless of whether
906 the new buffer could fit the contents of the old buffer
907 or not.
908 - allow a handle's buffering to change even if IO has
909 occurred (ANSI C spec. does not allow this, nor did
910 the previous implementation of IO.hSetBuffering).
911 - a non-standard extension is to allow the buffering
912 of semi-closed handles to change [sof 6/98]
913 -}
914 flushBuffer handle_
915
916 let state = initBufferState (haType handle_)
917 new_buf <-
918 case mode of
919 -- we always have a 1-character read buffer for
920 -- unbuffered handles: it's needed to
921 -- support hLookAhead.
922 NoBuffering -> allocateBuffer 1 ReadBuffer
923 LineBuffering -> allocateBuffer dEFAULT_BUFFER_SIZE state
924 BlockBuffering Nothing -> allocateBuffer dEFAULT_BUFFER_SIZE state
925 BlockBuffering (Just n) | n <= 0 -> ioe_bufsiz n
926 | otherwise -> allocateBuffer n state
927 writeIORef (haBuffer handle_) new_buf
928
929 -- for input terminals we need to put the terminal into
930 -- cooked or raw mode depending on the type of buffering.
931 is_tty <- fdIsTTY (haFD handle_)
932 when (is_tty && isReadableHandleType (haType handle_)) $
933 case mode of
934 NoBuffering -> setCooked (haFD handle_) False
935 _ -> setCooked (haFD handle_) True
936
937 -- throw away spare buffers, they might be the wrong size
938 writeIORef (haBuffers handle_) BufferListNil
939
940 return (handle_{ haBufferMode = mode })
941
942 -- -----------------------------------------------------------------------------
943 -- hFlush
944
945 -- The action `hFlush hdl' causes any items buffered for output
946 -- in handle `hdl' to be sent immediately to the operating
947 -- system.
948
949 hFlush :: Handle -> IO ()
950 hFlush handle =
951 wantWritableHandle "hFlush" handle $ \ handle_ -> do
952 buf <- readIORef (haBuffer handle_)
953 if bufferIsWritable buf && not (bufferEmpty buf)
954 then do flushed_buf <- flushWriteBuffer (haFD handle_) (haIsStream handle_) buf
955 writeIORef (haBuffer handle_) flushed_buf
956 else return ()
957
958
959 -- -----------------------------------------------------------------------------
960 -- Repositioning Handles
961
962 data HandlePosn = HandlePosn Handle HandlePosition
963
964 instance Eq HandlePosn where
965 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
966
967 instance Show HandlePosn where
968 showsPrec p (HandlePosn h pos) =
969 showsPrec p h . showString " at position " . shows pos
970
971 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
972 -- We represent it as an Integer on the Haskell side, but
973 -- cheat slightly in that hGetPosn calls upon a C helper
974 -- that reports the position back via (merely) an Int.
975 type HandlePosition = Integer
976
977 -- Computation `hGetPosn hdl' returns the current I/O position of
978 -- `hdl' as an abstract position. Computation `hSetPosn p' sets the
979 -- position of `hdl' to a previously obtained position `p'.
980
981 hGetPosn :: Handle -> IO HandlePosn
982 hGetPosn handle = do
983 posn <- hTell handle
984 return (HandlePosn handle posn)
985
986 hSetPosn :: HandlePosn -> IO ()
987 hSetPosn (HandlePosn h i) = hSeek h AbsoluteSeek i
988
989 -- ---------------------------------------------------------------------------
990 -- hSeek
991
992 {-
993 The action `hSeek hdl mode i' sets the position of handle
994 `hdl' depending on `mode'. If `mode' is
995
996 * AbsoluteSeek - The position of `hdl' is set to `i'.
997 * RelativeSeek - The position of `hdl' is set to offset `i' from
998 the current position.
999 * SeekFromEnd - The position of `hdl' is set to offset `i' from
1000 the end of the file.
1001
1002 Some handles may not be seekable (see `hIsSeekable'), or only
1003 support a subset of the possible positioning operations (e.g. it may
1004 only be possible to seek to the end of a tape, or to a positive
1005 offset from the beginning or current position).
1006
1007 It is not possible to set a negative I/O position, or for a physical
1008 file, an I/O position beyond the current end-of-file.
1009
1010 Note:
1011 - when seeking using `SeekFromEnd', positive offsets (>=0) means
1012 seeking at or past EOF.
1013
1014 - we possibly deviate from the report on the issue of seeking within
1015 the buffer and whether to flush it or not. The report isn't exactly
1016 clear here.
1017 -}
1018
1019 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
1020 deriving (Eq, Ord, Ix, Enum, Read, Show)
1021
1022 hSeek :: Handle -> SeekMode -> Integer -> IO ()
1023 hSeek handle mode offset =
1024 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
1025 # ifdef DEBUG_DUMP
1026 puts ("hSeek " ++ show (mode,offset) ++ "\n")
1027 # endif
1028 let ref = haBuffer handle_
1029 buf <- readIORef ref
1030 let r = bufRPtr buf
1031 w = bufWPtr buf
1032 fd = haFD handle_
1033
1034 let do_seek =
1035 throwErrnoIfMinus1Retry_ "hSeek"
1036 (c_lseek (fromIntegral (haFD handle_)) (fromIntegral offset) whence)
1037
1038 whence :: CInt
1039 whence = case mode of
1040 AbsoluteSeek -> sEEK_SET
1041 RelativeSeek -> sEEK_CUR
1042 SeekFromEnd -> sEEK_END
1043
1044 if bufferIsWritable buf
1045 then do new_buf <- flushWriteBuffer fd (haIsStream handle_) buf
1046 writeIORef ref new_buf
1047 do_seek
1048 else do
1049
1050 if mode == RelativeSeek && offset >= 0 && offset < fromIntegral (w - r)
1051 then writeIORef ref buf{ bufRPtr = r + fromIntegral offset }
1052 else do
1053
1054 new_buf <- flushReadBuffer (haFD handle_) buf
1055 writeIORef ref new_buf
1056 do_seek
1057
1058
1059 hTell :: Handle -> IO Integer
1060 hTell handle =
1061 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
1062
1063 #if defined(mingw32_TARGET_OS)
1064 -- urgh, on Windows we have to worry about \n -> \r\n translation,
1065 -- so we can't easily calculate the file position using the
1066 -- current buffer size. Just flush instead.
1067 flushBuffer handle_
1068 #endif
1069 let fd = fromIntegral (haFD handle_)
1070 posn <- fromIntegral `liftM`
1071 throwErrnoIfMinus1Retry "hGetPosn"
1072 (c_lseek fd 0 sEEK_CUR)
1073
1074 let ref = haBuffer handle_
1075 buf <- readIORef ref
1076
1077 let real_posn
1078 | bufferIsWritable buf = posn + fromIntegral (bufWPtr buf)
1079 | otherwise = posn - fromIntegral (bufWPtr buf - bufRPtr buf)
1080 # ifdef DEBUG_DUMP
1081 puts ("\nhGetPosn: (fd, posn, real_posn) = " ++ show (fd, posn, real_posn) ++ "\n")
1082 puts (" (bufWPtr, bufRPtr) = " ++ show (bufWPtr buf, bufRPtr buf) ++ "\n")
1083 # endif
1084 return real_posn
1085
1086 -- -----------------------------------------------------------------------------
1087 -- Handle Properties
1088
1089 -- A number of operations return information about the properties of a
1090 -- handle. Each of these operations returns `True' if the handle has
1091 -- the specified property, and `False' otherwise.
1092
1093 hIsOpen :: Handle -> IO Bool
1094 hIsOpen handle =
1095 withHandle_ "hIsOpen" handle $ \ handle_ -> do
1096 case haType handle_ of
1097 ClosedHandle -> return False
1098 SemiClosedHandle -> return False
1099 _ -> return True
1100
1101 hIsClosed :: Handle -> IO Bool
1102 hIsClosed handle =
1103 withHandle_ "hIsClosed" handle $ \ handle_ -> do
1104 case haType handle_ of
1105 ClosedHandle -> return True
1106 _ -> return False
1107
1108 {- not defined, nor exported, but mentioned
1109 here for documentation purposes:
1110
1111 hSemiClosed :: Handle -> IO Bool
1112 hSemiClosed h = do
1113 ho <- hIsOpen h
1114 hc <- hIsClosed h
1115 return (not (ho || hc))
1116 -}
1117
1118 hIsReadable :: Handle -> IO Bool
1119 hIsReadable (DuplexHandle _ _) = return True
1120 hIsReadable handle =
1121 withHandle_ "hIsReadable" handle $ \ handle_ -> do
1122 case haType handle_ of
1123 ClosedHandle -> ioe_closedHandle
1124 SemiClosedHandle -> ioe_closedHandle
1125 htype -> return (isReadableHandleType htype)
1126
1127 hIsWritable :: Handle -> IO Bool
1128 hIsWritable (DuplexHandle _ _) = return False
1129 hIsWritable handle =
1130 withHandle_ "hIsWritable" handle $ \ handle_ -> do
1131 case haType handle_ of
1132 ClosedHandle -> ioe_closedHandle
1133 SemiClosedHandle -> ioe_closedHandle
1134 htype -> return (isWritableHandleType htype)
1135
1136 -- Querying how a handle buffers its data:
1137
1138 hGetBuffering :: Handle -> IO BufferMode
1139 hGetBuffering handle =
1140 withHandle_ "hGetBuffering" handle $ \ handle_ -> do
1141 case haType handle_ of
1142 ClosedHandle -> ioe_closedHandle
1143 _ ->
1144 -- We're being non-standard here, and allow the buffering
1145 -- of a semi-closed handle to be queried. -- sof 6/98
1146 return (haBufferMode handle_) -- could be stricter..
1147
1148 hIsSeekable :: Handle -> IO Bool
1149 hIsSeekable handle =
1150 withHandle_ "hIsSeekable" handle $ \ handle_ -> do
1151 case haType handle_ of
1152 ClosedHandle -> ioe_closedHandle
1153 SemiClosedHandle -> ioe_closedHandle
1154 AppendHandle -> return False
1155 _ -> do t <- fdType (haFD handle_)
1156 return (t == RegularFile
1157 && (haIsBin handle_
1158 || tEXT_MODE_SEEK_ALLOWED))
1159
1160 -- -----------------------------------------------------------------------------
1161 -- Changing echo status
1162
1163 -- Non-standard GHC extension is to allow the echoing status
1164 -- of a handles connected to terminals to be reconfigured:
1165
1166 hSetEcho :: Handle -> Bool -> IO ()
1167 hSetEcho handle on = do
1168 isT <- hIsTerminalDevice handle
1169 if not isT
1170 then return ()
1171 else
1172 withHandle_ "hSetEcho" handle $ \ handle_ -> do
1173 case haType handle_ of
1174 ClosedHandle -> ioe_closedHandle
1175 _ -> setEcho (haFD handle_) on
1176
1177 hGetEcho :: Handle -> IO Bool
1178 hGetEcho handle = do
1179 isT <- hIsTerminalDevice handle
1180 if not isT
1181 then return False
1182 else
1183 withHandle_ "hGetEcho" handle $ \ handle_ -> do
1184 case haType handle_ of
1185 ClosedHandle -> ioe_closedHandle
1186 _ -> getEcho (haFD handle_)
1187
1188 hIsTerminalDevice :: Handle -> IO Bool
1189 hIsTerminalDevice handle = do
1190 withHandle_ "hIsTerminalDevice" handle $ \ handle_ -> do
1191 case haType handle_ of
1192 ClosedHandle -> ioe_closedHandle
1193 _ -> fdIsTTY (haFD handle_)
1194
1195 -- -----------------------------------------------------------------------------
1196 -- hSetBinaryMode
1197
1198 -- | On Windows, reading a file in text mode (which is the default) will
1199 -- translate CRLF to LF, and writing will translate LF to CRLF. This
1200 -- is usually what you want with text files. With binary files this is
1201 -- undesirable; also, as usual under Microsoft operating systems, text
1202 -- mode treats control-Z as EOF. Setting binary mode using
1203 -- 'hSetBinaryMode' turns off all special treatment of end-of-line and
1204 -- end-of-file characters.
1205 --
1206 hSetBinaryMode :: Handle -> Bool -> IO ()
1207 hSetBinaryMode handle bin =
1208 withAllHandles__ "hSetBinaryMode" handle $ \ handle_ ->
1209 do throwErrnoIfMinus1_ "hSetBinaryMode"
1210 (setmode (fromIntegral (haFD handle_)) bin)
1211 return handle_{haIsBin=bin}
1212
1213 foreign import ccall unsafe "__hscore_setmode"
1214 setmode :: CInt -> Bool -> IO CInt
1215
1216 -- ---------------------------------------------------------------------------
1217 -- debugging
1218
1219 #ifdef DEBUG_DUMP
1220 puts :: String -> IO ()
1221 puts s = withCString s $ \cstr -> do write_off_ba 1 False cstr 0 (fromIntegral (length s))
1222 return ()
1223 #endif
1224
1225 -- -----------------------------------------------------------------------------
1226 -- wrappers to platform-specific constants:
1227
1228 foreign import ccall unsafe "__hscore_supportsTextMode"
1229 tEXT_MODE_SEEK_ALLOWED :: Bool
1230
1231 foreign import ccall unsafe "__hscore_bufsiz" dEFAULT_BUFFER_SIZE :: Int
1232 foreign import ccall unsafe "__hscore_seek_cur" sEEK_CUR :: CInt
1233 foreign import ccall unsafe "__hscore_seek_set" sEEK_SET :: CInt
1234 foreign import ccall unsafe "__hscore_seek_end" sEEK_END :: CInt