2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[IOHandle]{Module @IOHandle@}
7 This module defines Haskell {\em handles} and the basic operations
8 which are supported for them.
11 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
20 import ArrBase ( ByteArray(..) )
21 import PrelRead ( Read )
22 import PrelList (span)
29 #ifndef __PARALLEL_HASKELL__
30 import Foreign ( ForeignObj, Addr, makeForeignObj, writeForeignObj )
33 #if defined(__CONCURRENT_HASKELL__)
39 %*********************************************************
41 \subsection{Types @FilePath@, @Handle@, @Handle__@}
43 %*********************************************************
45 The @Handle@ and @Handle__@ types are defined in @IOBase@.
48 type FilePath = String
50 {-# INLINE newHandle #-}
51 {-# INLINE readHandle #-}
52 {-# INLINE writeHandle #-}
53 newHandle :: Handle__ -> IO Handle
54 readHandle :: Handle -> IO Handle__
55 writeHandle :: Handle -> Handle__ -> IO ()
57 #if defined(__CONCURRENT_HASKELL__)
62 newHandle v = stToIO (newVar v)
63 readHandle h = stToIO (readVar h)
64 writeHandle h v = stToIO (writeVar h v)
69 %*********************************************************
71 \subsection{Functions}
73 %*********************************************************
76 #ifndef __PARALLEL_HASKELL__
77 filePtr :: Handle__ -> ForeignObj
79 filePtr :: Handle__ -> Addr
81 filePtr (SemiClosedHandle fp _) = fp
82 filePtr (ReadHandle fp _ _) = fp
83 filePtr (WriteHandle fp _ _) = fp
84 filePtr (AppendHandle fp _ _) = fp
85 filePtr (ReadWriteHandle fp _ _) = fp
87 bufferMode :: Handle__ -> Maybe BufferMode
88 bufferMode (ReadHandle _ m _) = m
89 bufferMode (WriteHandle _ m _) = m
90 bufferMode (AppendHandle _ m _) = m
91 bufferMode (ReadWriteHandle _ m _) = m
93 markHandle :: Handle__ -> Handle__
94 markHandle h@(ReadHandle fp m b)
96 | otherwise = ReadHandle fp m True
97 markHandle h@(WriteHandle fp m b)
99 | otherwise = WriteHandle fp m True
100 markHandle h@(AppendHandle fp m b)
102 | otherwise = AppendHandle fp m True
103 markHandle h@(ReadWriteHandle fp m b)
105 | otherwise = ReadWriteHandle fp m True
108 -------------------------------------------
110 %*********************************************************
112 \subsection[StdHandles]{Standard handles}
114 %*********************************************************
116 Three handles are allocated during program initialisation. The first
117 two manage input or output from the Haskell program's standard input
118 or output channel respectively. The third manages output to the
119 standard error channel. These handles are initially open.
122 stdin, stdout, stderr :: Handle
124 stdin = unsafePerformPrimIO (
125 _ccall_ getLock (``stdin''::Addr) 0 >>= \ rc ->
127 0 -> new_handle ClosedHandle
129 #ifndef __PARALLEL_HASKELL__
130 makeForeignObj (``stdin''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
131 new_handle (ReadHandle fp Nothing False)
133 new_handle (ReadHandle ``stdin'' Nothing False)
135 _ -> constructError "stdin" >>= \ ioError ->
136 new_handle (ErrorHandle ioError)
141 new_handle x = ioToST (newHandle x)
143 stdout = unsafePerformPrimIO (
144 _ccall_ getLock (``stdout''::Addr) 1 >>= \ rc ->
146 0 -> new_handle ClosedHandle
148 #ifndef __PARALLEL_HASKELL__
149 makeForeignObj (``stdout''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
150 new_handle (WriteHandle fp Nothing False)
152 new_handle (WriteHandle ``stdout'' Nothing False)
154 _ -> constructError "stdout" >>= \ ioError ->
155 new_handle (ErrorHandle ioError)
160 new_handle x = ioToST (newHandle x)
162 stderr = unsafePerformPrimIO (
163 _ccall_ getLock (``stderr''::Addr) 1 >>= \ rc ->
165 0 -> new_handle ClosedHandle
167 #ifndef __PARALLEL_HASKELL__
168 makeForeignObj (``stderr''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
169 new_handle (WriteHandle fp (Just NoBuffering) False)
171 new_handle (WriteHandle ``stderr'' (Just NoBuffering) False)
173 _ -> constructError "stderr" >>= \ ioError ->
174 new_handle (ErrorHandle ioError)
179 new_handle x = ioToST (newHandle x)
182 %*********************************************************
184 \subsection[OpeningClosing]{Opening and Closing Files}
186 %*********************************************************
189 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
190 deriving (Eq, Ord, Ix, Enum, Read, Show)
192 openFile :: FilePath -> IOMode -> IO Handle
195 stToIO (_ccall_ openFile f m') >>= \ ptr ->
196 if ptr /= ``NULL'' then
197 #ifndef __PARALLEL_HASKELL__
198 makeForeignObj ptr ((``&freeFile'')::Addr) `thenIO_Prim` \ fp ->
199 newHandle (htype fp Nothing False)
201 newHandle (htype ptr Nothing False)
204 stToIO (constructError "openFile") >>= \ ioError@(IOError hn iot msg) ->
206 improved_error -- a HACK, I guess
208 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
209 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
210 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
219 ReadWriteMode -> "r+"
222 ReadMode -> ReadHandle
223 WriteMode -> WriteHandle
224 AppendMode -> AppendHandle
225 ReadWriteMode -> ReadWriteHandle
228 Computation $openFile file mode$ allocates and returns a new, open
229 handle to manage the file {\em file}. It manages input if {\em mode}
230 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
231 and both input and output if mode is $ReadWriteMode$.
233 If the file does not exist and it is opened for output, it should be
234 created as a new file. If {\em mode} is $WriteMode$ and the file
235 already exists, then it should be truncated to zero length. The
236 handle is positioned at the end of the file if {\em mode} is
237 $AppendMode$, and otherwise at the beginning (in which case its
238 internal position is 0).
240 Implementations should enforce, locally to the Haskell process,
241 multiple-reader single-writer locking on files, which is to say that
242 there may either be many handles on the same file which manage input,
243 or just one handle on the file which manages output. If any open or
244 semi-closed handle is managing a file for output, no new handle can be
245 allocated for that file. If any open or semi-closed handle is
246 managing a file for input, new handles can only be allocated if they
247 do not manage output.
249 Two files are the same if they have the same absolute name. An
250 implementation is free to impose stricter conditions.
253 hClose :: Handle -> IO ()
256 readHandle handle >>= \ htype ->
258 ErrorHandle ioError ->
259 writeHandle handle htype >>
262 writeHandle handle htype >>
263 ioe_closedHandle handle
264 SemiClosedHandle fp (buf,_) ->
265 (if buf /= ``NULL'' then
268 returnPrimIO ()) `thenIO_Prim` \ () ->
269 _casm_ `` %r = (char *)%0; '' fp `thenIO_Prim` \ fp_a ->
270 if fp_a /= (``NULL''::Addr) then -- Under what condition can this be NULL?
271 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
272 {- We explicitly close a file object so that we can be told
273 if there were any errors. Note that after @hClose@
274 has been performed, the ForeignObj embedded in the Handle
275 is still lying around in the heap, so care is taken
276 to avoid closing the file object when the ForeignObj
279 #ifndef __PARALLEL_HASKELL__
280 -- Mark the foreign object data value as gone to the finaliser (freeFile())
281 writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
283 writeHandle handle ClosedHandle
285 writeHandle handle htype >>
286 constructErrorAndFail "hClose"
289 writeHandle handle htype
291 let fp = filePtr other in
292 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
294 #ifndef __PARALLEL_HASKELL__
295 -- Mark the foreign object data
296 writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
298 writeHandle handle ClosedHandle
300 writeHandle handle htype >>
301 constructErrorAndFail "hClose"
304 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
305 computation finishes, any items buffered for output and not already
306 sent to the operating system are flushed as for $flush$.
308 %*********************************************************
310 \subsection[EOF]{Detecting the End of Input}
312 %*********************************************************
315 For a handle {\em hdl} which attached to a physical file, $hFileSize
316 hdl$ returns the size of {\em hdl} in terms of the number of items
317 which can be read from {\em hdl}.
320 hFileSize :: Handle -> IO Integer
322 readHandle handle >>= \ htype ->
324 ErrorHandle ioError ->
325 writeHandle handle htype >>
328 writeHandle handle htype >>
329 ioe_closedHandle handle
330 SemiClosedHandle _ _ ->
331 writeHandle handle htype >>
332 ioe_closedHandle handle
334 -- HACK! We build a unique MP_INT of the right shape to hold
335 -- a single unsigned word, and we let the C routine change the data bits
336 _casm_ ``%r = 1;'' `thenIO_Prim` \ (I# hack#) ->
337 case int2Integer# hack# of
338 result@(J# _ _ d#) ->
340 bogus_bounds = (error "fileSize"::(Int,Int))
342 _ccall_ fileSize (filePtr other) (ByteArray bogus_bounds d#)
343 `thenIO_Prim` \ rc ->
344 writeHandle handle htype >>
348 constructErrorAndFail "hFileSize"
351 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
352 $True$ if no further input can be taken from {\em hdl} or for a
353 physical file, if the current I/O position is equal to the length of
354 the file. Otherwise, it returns $False$.
357 hIsEOF :: Handle -> IO Bool
359 readHandle handle >>= \ htype ->
361 ErrorHandle ioError ->
362 writeHandle handle htype >>
365 writeHandle handle htype >>
366 ioe_closedHandle handle
367 SemiClosedHandle _ _ ->
368 writeHandle handle htype >>
369 ioe_closedHandle handle
371 writeHandle handle htype >>
372 fail (IOError (Just handle) IllegalOperation "handle is not open for reading")
373 AppendHandle _ _ _ ->
374 writeHandle handle htype >>
375 fail (IOError (Just handle) IllegalOperation "handle is not open for reading")
377 _ccall_ fileEOF (filePtr other) `thenIO_Prim` \ rc ->
378 writeHandle handle (markHandle htype) >>
382 _ -> constructErrorAndFail "hIsEOF"
388 %*********************************************************
390 \subsection[Buffering]{Buffering Operations}
392 %*********************************************************
394 Three kinds of buffering are supported: line-buffering,
395 block-buffering or no-buffering. See @IOBase@ for definition
396 and further explanation of what the type represent.
398 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
399 handle {\em hdl} on subsequent reads and writes.
403 If {\em mode} is @LineBuffering@, line-buffering should be
406 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
407 should be enabled if possible. The size of the buffer is {\em n} items
408 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
410 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
413 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
414 to @NoBuffering@, then any items in the output buffer are written to
415 the device, and any items in the input buffer are discarded. The
416 default buffering mode when a handle is opened is
417 implementation-dependent and may depend on the object which is
418 attached to that handle.
421 hSetBuffering :: Handle -> BufferMode -> IO ()
423 hSetBuffering handle mode =
425 (BlockBuffering (Just n))
426 | n <= 0 -> fail (IOError (Just handle) InvalidArgument "illegal buffer size")
428 readHandle handle >>= \ htype ->
429 if isMarked htype then
430 writeHandle handle htype >>
431 fail (IOError (Just handle)
433 "can't set buffering for a dirty handle")
436 ErrorHandle ioError ->
437 writeHandle handle htype >>
440 writeHandle handle htype >>
441 ioe_closedHandle handle
442 SemiClosedHandle _ _ ->
443 writeHandle handle htype >>
444 ioe_closedHandle handle
446 _ccall_ setBuffering (filePtr other) bsize
447 `thenIO_Prim` \ rc ->
449 writeHandle handle ((hcon other) (filePtr other) (Just mode) True)
453 writeHandle handle htype >>
454 constructErrorAndFail "hSetBuffering"
457 isMarked :: Handle__ -> Bool
458 isMarked (ReadHandle fp m b) = b
459 isMarked (WriteHandle fp m b) = b
460 isMarked (AppendHandle fp m b) = b
461 isMarked (ReadWriteHandle fp m b) = b
467 BlockBuffering Nothing -> -2
468 BlockBuffering (Just n) -> n
470 #ifndef __PARALLEL_HASKELL__
471 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
473 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
475 hcon (ReadHandle _ _ _) = ReadHandle
476 hcon (WriteHandle _ _ _) = WriteHandle
477 hcon (AppendHandle _ _ _) = AppendHandle
478 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
481 Computation $flush hdl$ causes any items buffered for output in handle
482 {\em hdl} to be sent immediately to the operating system.
485 hFlush :: Handle -> IO ()
487 readHandle handle >>= \ htype ->
489 ErrorHandle ioError ->
490 writeHandle handle htype >>
493 writeHandle handle htype >>
494 ioe_closedHandle handle
495 SemiClosedHandle _ _ ->
496 writeHandle handle htype >>
497 ioe_closedHandle handle
499 _ccall_ flushFile (filePtr other) `thenIO_Prim` \ rc ->
500 writeHandle handle (markHandle htype) >>
504 constructErrorAndFail "hFlush"
508 %*********************************************************
510 \subsection[Seeking]{Repositioning Handles}
512 %*********************************************************
515 data HandlePosn = HandlePosn Handle Int
517 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
518 deriving (Eq, Ord, Ix, Enum, Read, Show)
521 Computation $hGetPosn hdl$ returns the current I/O
522 position of {\em hdl} as an abstract position. Computation
523 $hSetPosn p$ sets the position of {\em hdl}
524 to a previously obtained position {\em p}.
527 hGetPosn :: Handle -> IO HandlePosn
529 readHandle handle >>= \ htype ->
531 ErrorHandle ioError ->
532 writeHandle handle htype >>
535 writeHandle handle htype >>
536 ioe_closedHandle handle
537 SemiClosedHandle _ _ ->
538 writeHandle handle htype >>
539 ioe_closedHandle handle
541 _ccall_ getFilePosn (filePtr other) `thenIO_Prim` \ posn ->
542 writeHandle handle htype >>
544 return (HandlePosn handle posn)
546 constructErrorAndFail "hGetPosn"
548 hSetPosn :: HandlePosn -> IO ()
549 hSetPosn (HandlePosn handle posn) =
550 readHandle handle >>= \ htype ->
552 ErrorHandle ioError ->
553 writeHandle handle htype >>
556 writeHandle handle htype >>
557 ioe_closedHandle handle
558 SemiClosedHandle _ _ ->
559 writeHandle handle htype >>
560 ioe_closedHandle handle
561 AppendHandle _ _ _ ->
562 writeHandle handle htype >>
563 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
565 _ccall_ setFilePosn (filePtr other) posn `thenIO_Prim` \ rc ->
566 writeHandle handle (markHandle htype) >>
570 constructErrorAndFail "hSetPosn"
573 Computation $hSeek hdl mode i$ sets the position of handle
574 {\em hdl} depending on $mode$. If {\em mode} is
576 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
577 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
578 the current position.
579 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
581 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
582 the beginning of the file.
585 Some handles may not be seekable $hIsSeekable$, or only support a
586 subset of the possible positioning operations (e.g. it may only be
587 possible to seek to the end of a tape, or to a positive offset from
588 the beginning or current position).
590 It is not possible to set a negative I/O position, or for a physical
591 file, an I/O position beyond the current end-of-file.
594 hSeek :: Handle -> SeekMode -> Integer -> IO ()
595 hSeek handle mode offset@(J# _ s# d#) =
596 readHandle handle >>= \ htype ->
598 ErrorHandle ioError ->
599 writeHandle handle htype >>
602 writeHandle handle htype >>
603 ioe_closedHandle handle
604 SemiClosedHandle _ _ ->
605 writeHandle handle htype >>
606 ioe_closedHandle handle
607 AppendHandle _ _ _ ->
608 writeHandle handle htype >>
609 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
611 _ccall_ seekFile (filePtr other) whence (I# s#) (ByteArray (0,0) d#)
612 `thenIO_Prim` \ rc ->
613 writeHandle handle (markHandle htype) >>
617 constructErrorAndFail "hSeek"
620 whence = case mode of
621 AbsoluteSeek -> ``SEEK_SET''
622 RelativeSeek -> ``SEEK_CUR''
623 SeekFromEnd -> ``SEEK_END''
626 %*********************************************************
628 \subsection[Query]{Handle Properties}
630 %*********************************************************
632 A number of operations return information about the properties of a
633 handle. Each of these operations returns $True$ if the
634 handle has the specified property, and $False$
637 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
638 {\em hdl} is not block-buffered. Otherwise it returns
639 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
640 $( Just n )$ for block-buffering of {\em n} bytes.
643 hIsOpen :: Handle -> IO Bool
645 readHandle handle >>= \ htype ->
647 ErrorHandle ioError ->
648 writeHandle handle htype >>
651 writeHandle handle htype >>
653 SemiClosedHandle _ _ ->
654 writeHandle handle htype >>
657 writeHandle handle htype >>
660 hIsClosed :: Handle -> IO Bool
662 readHandle handle >>= \ htype ->
664 ErrorHandle ioError ->
665 writeHandle handle htype >>
668 writeHandle handle htype >>
671 writeHandle handle htype >>
674 hIsReadable :: Handle -> IO Bool
676 readHandle handle >>= \ htype ->
678 ErrorHandle ioError ->
679 writeHandle handle htype >>
682 writeHandle handle htype >>
683 ioe_closedHandle handle
684 SemiClosedHandle _ _ ->
685 writeHandle handle htype >>
686 ioe_closedHandle handle
688 writeHandle handle htype >>
689 return (isReadable other)
691 isReadable (ReadHandle _ _ _) = True
692 isReadable (ReadWriteHandle _ _ _) = True
695 hIsWritable :: Handle -> IO Bool
697 readHandle handle >>= \ htype ->
699 ErrorHandle ioError ->
700 writeHandle handle htype >>
703 writeHandle handle htype >>
704 ioe_closedHandle handle
705 SemiClosedHandle _ _ ->
706 writeHandle handle htype >>
707 ioe_closedHandle handle
709 writeHandle handle htype >>
710 return (isWritable other)
712 isWritable (AppendHandle _ _ _) = True
713 isWritable (WriteHandle _ _ _) = True
714 isWritable (ReadWriteHandle _ _ _) = True
717 getBufferMode :: Handle__ -> PrimIO Handle__
718 getBufferMode htype =
719 case bufferMode htype of
720 Just x -> returnPrimIO htype
722 _ccall_ getBufferMode (filePtr htype) `thenPrimIO` \ rc ->
726 0 -> Just NoBuffering
727 -1 -> Just LineBuffering
728 -2 -> Just (BlockBuffering Nothing)
730 n -> Just (BlockBuffering (Just n))
732 returnPrimIO (case htype of
733 ReadHandle fp _ b -> ReadHandle fp mode b
734 WriteHandle fp _ b -> WriteHandle fp mode b
735 AppendHandle fp _ b -> AppendHandle fp mode b
736 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
738 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
739 hIsBlockBuffered handle =
740 readHandle handle >>= \ htype ->
742 ErrorHandle ioError ->
743 writeHandle handle htype >>
746 writeHandle handle htype >>
747 ioe_closedHandle handle
748 SemiClosedHandle _ _ ->
749 writeHandle handle htype >>
750 ioe_closedHandle handle
752 getBufferMode other `thenIO_Prim` \ other ->
753 case bufferMode other of
754 Just (BlockBuffering size) ->
755 writeHandle handle other >>
758 writeHandle handle other >>
759 return (False, Nothing)
761 constructErrorAndFail "hIsBlockBuffered"
763 hIsLineBuffered :: Handle -> IO Bool
764 hIsLineBuffered handle =
765 readHandle handle >>= \ htype ->
767 ErrorHandle ioError ->
768 writeHandle handle htype >>
771 writeHandle handle htype >>
772 ioe_closedHandle handle
773 SemiClosedHandle _ _ ->
774 writeHandle handle htype >>
775 ioe_closedHandle handle
777 getBufferMode other `thenIO_Prim` \ other ->
778 case bufferMode other of
779 Just LineBuffering ->
780 writeHandle handle other >>
783 writeHandle handle other >>
786 constructErrorAndFail "hIsLineBuffered"
788 hIsNotBuffered :: Handle -> IO Bool
789 hIsNotBuffered handle =
790 readHandle handle >>= \ htype ->
792 ErrorHandle ioError ->
793 writeHandle handle htype >>
796 writeHandle handle htype >>
797 ioe_closedHandle handle
798 SemiClosedHandle _ _ ->
799 writeHandle handle htype >>
800 ioe_closedHandle handle
802 getBufferMode other `thenIO_Prim` \ other ->
803 case bufferMode other of
805 writeHandle handle other >>
808 writeHandle handle other >>
811 constructErrorAndFail "hIsNotBuffered"
813 hGetBuffering :: Handle -> IO BufferMode
814 hGetBuffering handle =
815 readHandle handle >>= \ htype ->
817 ErrorHandle ioError ->
818 writeHandle handle htype >>
821 writeHandle handle htype >>
822 ioe_closedHandle handle
823 SemiClosedHandle _ _ ->
824 writeHandle handle htype >>
825 ioe_closedHandle handle
827 getBufferMode other `thenIO_Prim` \ other ->
828 case bufferMode other of
830 writeHandle handle other >>
833 constructErrorAndFail "hGetBuffering"
835 hIsSeekable :: Handle -> IO Bool
837 readHandle handle >>= \ htype ->
839 ErrorHandle ioError ->
840 writeHandle handle htype >>
843 writeHandle handle htype >>
844 ioe_closedHandle handle
845 SemiClosedHandle _ _ ->
846 writeHandle handle htype >>
847 ioe_closedHandle handle
848 AppendHandle _ _ _ ->
849 writeHandle handle htype >>
852 _ccall_ seekFileP (filePtr other) `thenIO_Prim` \ rc ->
853 writeHandle handle htype >>
857 _ -> constructErrorAndFail "hIsSeekable"
861 %*********************************************************
863 \subsection{Miscellaneous}
865 %*********************************************************
867 These two functions are meant to get things out of @IOErrors@. They don't!
870 ioeGetFileName :: IOError -> Maybe FilePath
871 ioeGetErrorString :: IOError -> String
872 ioeGetHandle :: IOError -> Maybe Handle
874 ioeGetHandle (IOError h _ _) = h
875 ioeGetErrorString (IOError _ iot str) =
880 ioeGetFileName (IOError _ _ str) =
881 case span (/=':') str of
887 Internal function for creating an @IOError@ representing the
888 access of a closed file.
892 ioe_closedHandle :: Handle -> IO a
893 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")