2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[PrelHandle]{Module @PrelHandle@}
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" #-}
15 module PrelHandle where
18 import PrelArr ( ByteArray(..), newVar, readVar, writeVar )
19 import PrelRead ( Read )
20 import PrelList ( span )
22 import PrelUnsafe ( unsafePerformIO )
27 import PrelErr ( error )
31 #ifndef __PARALLEL_HASKELL__
32 import PrelForeign ( ForeignObj, makeForeignObj, writeForeignObj )
35 import PrelConc -- concurrent only
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__)
59 -- Use MVars for concurrent Haskell
60 newHandle hc = newMVar hc >>= \ h ->
63 readHandle (Handle h) = takeMVar h
64 writeHandle (Handle h) hc = putMVar h hc
68 -- Use ordinary MutableVars for non-concurrent Haskell
69 newHandle hc = stToIO (newVar hc >>= \ h ->
72 readHandle (Handle h) = stToIO (readVar h)
73 writeHandle (Handle h) hc = stToIO (writeVar h hc)
78 %*********************************************************
80 \subsection{Functions}
82 %*********************************************************
85 #ifndef __PARALLEL_HASKELL__
86 filePtr :: Handle__ -> ForeignObj
88 filePtr :: Handle__ -> Addr
90 filePtr (SemiClosedHandle fp _) = fp
91 filePtr (ReadHandle fp _ _) = fp
92 filePtr (WriteHandle fp _ _) = fp
93 filePtr (AppendHandle fp _ _) = fp
94 filePtr (ReadWriteHandle fp _ _) = fp
96 bufferMode :: Handle__ -> Maybe BufferMode
97 bufferMode (ReadHandle _ m _) = m
98 bufferMode (WriteHandle _ m _) = m
99 bufferMode (AppendHandle _ m _) = m
100 bufferMode (ReadWriteHandle _ m _) = m
102 markHandle :: Handle__ -> Handle__
103 markHandle h@(ReadHandle fp m b)
105 | otherwise = ReadHandle fp m True
106 markHandle h@(WriteHandle fp m b)
108 | otherwise = WriteHandle fp m True
109 markHandle h@(AppendHandle fp m b)
111 | otherwise = AppendHandle fp m True
112 markHandle h@(ReadWriteHandle fp m b)
114 | otherwise = ReadWriteHandle fp m True
117 -------------------------------------------
119 %*********************************************************
121 \subsection[StdHandles]{Standard handles}
123 %*********************************************************
125 Three handles are allocated during program initialisation. The first
126 two manage input or output from the Haskell program's standard input
127 or output channel respectively. The third manages output to the
128 standard error channel. These handles are initially open.
131 stdin, stdout, stderr :: Handle
133 stdin = unsafePerformIO (do
134 rc <- _ccall_ getLock (``stdin''::Addr) 0
136 0 -> newHandle ClosedHandle
138 #ifndef __PARALLEL_HASKELL__
139 fp <- makeForeignObj (``stdin''::Addr) (``&freeStdFile''::Addr)
140 newHandle (ReadHandle fp Nothing False)
142 newHandle (ReadHandle ``stdin'' Nothing False)
144 _ -> do ioError <- constructError "stdin"
145 newHandle (ErrorHandle ioError)
148 stdout = unsafePerformIO (do
149 rc <- _ccall_ getLock (``stdout''::Addr) 1
151 0 -> newHandle ClosedHandle
153 #ifndef __PARALLEL_HASKELL__
154 fp <- makeForeignObj (``stdout''::Addr) (``&freeStdFile''::Addr)
155 newHandle (WriteHandle fp Nothing False)
157 newHandle (WriteHandle ``stdout'' Nothing False)
159 _ -> do ioError <- constructError "stdout"
160 newHandle (ErrorHandle ioError)
163 stderr = unsafePerformIO (do
164 rc <- _ccall_ getLock (``stderr''::Addr) 1
166 0 -> newHandle ClosedHandle
168 #ifndef __PARALLEL_HASKELL__
169 fp <- makeForeignObj (``stderr''::Addr) (``&freeStdFile''::Addr)
170 newHandle (WriteHandle fp (Just NoBuffering) False)
172 newHandle (WriteHandle ``stderr'' (Just NoBuffering) False)
174 _ -> do ioError <- constructError "stderr"
175 newHandle (ErrorHandle ioError)
179 %*********************************************************
181 \subsection[OpeningClosing]{Opening and Closing Files}
183 %*********************************************************
186 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
187 deriving (Eq, Ord, Ix, Enum, Read, Show)
192 deriving (Eq, Read, Show)
194 openFile :: FilePath -> IOMode -> IO Handle
195 openFile fp im = openFileEx fp (TextMode im)
197 openFileEx :: FilePath -> IOModeEx -> IO Handle
200 ptr <- _ccall_ openFile f m'
201 if ptr /= ``NULL'' then do
202 #ifndef __PARALLEL_HASKELL__
203 fp <- makeForeignObj ptr ((``&freeFile'')::Addr)
204 newHandle (htype fp Nothing False)
206 newHandle (htype ptr Nothing False)
209 constructErrorAndFailWithInfo "openFile" f
212 BinaryMode imo -> imo
216 BinaryMode _ -> imo' ++ "b"
224 ReadWriteMode -> "r+"
227 ReadMode -> ReadHandle
228 WriteMode -> WriteHandle
229 AppendMode -> AppendHandle
230 ReadWriteMode -> ReadWriteHandle
233 Computation $openFile file mode$ allocates and returns a new, open
234 handle to manage the file {\em file}. It manages input if {\em mode}
235 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
236 and both input and output if mode is $ReadWriteMode$.
238 If the file does not exist and it is opened for output, it should be
239 created as a new file. If {\em mode} is $WriteMode$ and the file
240 already exists, then it should be truncated to zero length. The
241 handle is positioned at the end of the file if {\em mode} is
242 $AppendMode$, and otherwise at the beginning (in which case its
243 internal position is 0).
245 Implementations should enforce, locally to the Haskell process,
246 multiple-reader single-writer locking on files, which is to say that
247 there may either be many handles on the same file which manage input,
248 or just one handle on the file which manages output. If any open or
249 semi-closed handle is managing a file for output, no new handle can be
250 allocated for that file. If any open or semi-closed handle is
251 managing a file for input, new handles can only be allocated if they
252 do not manage output.
254 Two files are the same if they have the same absolute name. An
255 implementation is free to impose stricter conditions.
258 hClose :: Handle -> IO ()
261 htype <- readHandle handle
263 ErrorHandle ioError -> do
264 writeHandle handle htype
267 writeHandle handle htype
268 ioe_closedHandle handle
269 SemiClosedHandle fp (buf,_) -> do
270 (if buf /= ``NULL'' then
274 fp_a <- _casm_ `` %r = (char *)%0; '' fp
275 if fp_a /= (``NULL''::Addr) then do
276 -- Under what condition can this be NULL?
277 rc <- _ccall_ closeFile fp
278 {- We explicitly close a file object so that we can be told
279 if there were any errors. Note that after @hClose@
280 has been performed, the ForeignObj embedded in the Handle
281 is still lying around in the heap, so care is taken
282 to avoid closing the file object when the ForeignObj
285 #ifndef __PARALLEL_HASKELL__
286 -- Mark the foreign object data value as
287 -- gone to the finaliser (freeFile())
288 writeForeignObj fp ``NULL''
290 writeHandle handle ClosedHandle
292 writeHandle handle htype
293 constructErrorAndFail "hClose"
295 else writeHandle handle htype
298 let fp = filePtr other
299 rc <- _ccall_ closeFile fp
301 #ifndef __PARALLEL_HASKELL__
302 -- Mark the foreign object data
303 writeForeignObj fp ``NULL''
305 writeHandle handle ClosedHandle
307 writeHandle handle htype
308 constructErrorAndFail "hClose"
311 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
312 computation finishes, any items buffered for output and not already
313 sent to the operating system are flushed as for $flush$.
315 %*********************************************************
317 \subsection[EOF]{Detecting the End of Input}
319 %*********************************************************
322 For a handle {\em hdl} which attached to a physical file, $hFileSize
323 hdl$ returns the size of {\em hdl} in terms of the number of items
324 which can be read from {\em hdl}.
327 hFileSize :: Handle -> IO Integer
328 hFileSize handle = do
329 htype <- readHandle handle
331 ErrorHandle ioError -> do
332 writeHandle handle htype
335 writeHandle handle htype
336 ioe_closedHandle handle
337 SemiClosedHandle _ _ -> do
338 writeHandle handle htype
339 ioe_closedHandle handle
341 -- HACK! We build a unique MP_INT of the right shape to hold
342 -- a single unsigned word, and we let the C routine
343 -- change the data bits
345 -- For some reason, this fails to typecheck if converted to a do
347 _casm_ ``%r = 1;'' >>= \(I# hack#) ->
348 case int2Integer# hack# of
349 result@(J# _ _ d#) -> do
350 let bogus_bounds = (error "fileSize"::(Int,Int))
351 rc <- _ccall_ fileSize (filePtr other)
352 (ByteArray bogus_bounds d#)
353 writeHandle handle htype
357 constructErrorAndFail "hFileSize"
360 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
361 $True$ if no further input can be taken from {\em hdl} or for a
362 physical file, if the current I/O position is equal to the length of
363 the file. Otherwise, it returns $False$.
366 hIsEOF :: Handle -> IO Bool
368 htype <- readHandle handle
370 ErrorHandle ioError -> do
371 writeHandle handle htype
374 writeHandle handle htype
375 ioe_closedHandle handle
376 SemiClosedHandle _ _ -> do
377 writeHandle handle htype
378 ioe_closedHandle handle
379 WriteHandle _ _ _ -> do
380 writeHandle handle htype
381 fail (IOError (Just handle) IllegalOperation
382 "handle is not open for reading")
383 AppendHandle _ _ _ -> do
384 writeHandle handle htype
385 fail (IOError (Just handle) IllegalOperation
386 "handle is not open for reading")
388 rc <- _ccall_ fileEOF (filePtr other)
389 writeHandle handle (markHandle htype)
393 _ -> constructErrorAndFail "hIsEOF"
399 %*********************************************************
401 \subsection[Buffering]{Buffering Operations}
403 %*********************************************************
405 Three kinds of buffering are supported: line-buffering,
406 block-buffering or no-buffering. See @IOBase@ for definition
407 and further explanation of what the type represent.
409 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
410 handle {\em hdl} on subsequent reads and writes.
414 If {\em mode} is @LineBuffering@, line-buffering should be
417 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
418 should be enabled if possible. The size of the buffer is {\em n} items
419 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
421 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
424 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
425 to @NoBuffering@, then any items in the output buffer are written to
426 the device, and any items in the input buffer are discarded. The
427 default buffering mode when a handle is opened is
428 implementation-dependent and may depend on the object which is
429 attached to that handle.
432 hSetBuffering :: Handle -> BufferMode -> IO ()
434 hSetBuffering handle mode =
436 BlockBuffering (Just n)
437 | n <= 0 -> fail (IOError (Just handle) InvalidArgument
438 "illegal buffer size")
440 htype <- readHandle handle
441 if isMarked htype then do
442 writeHandle handle htype
443 fail (IOError (Just handle)
445 "can't set buffering for a dirty handle")
448 ErrorHandle ioError -> do
449 writeHandle handle htype
452 writeHandle handle htype
453 ioe_closedHandle handle
454 SemiClosedHandle _ _ -> do
455 writeHandle handle htype
456 ioe_closedHandle handle
458 rc <- _ccall_ setBuffering (filePtr other) bsize
460 writeHandle handle ((hcon other) (filePtr other)
463 writeHandle handle htype
464 constructErrorAndFail "hSetBuffering"
467 isMarked :: Handle__ -> Bool
468 isMarked (ReadHandle fp m b) = b
469 isMarked (WriteHandle fp m b) = b
470 isMarked (AppendHandle fp m b) = b
471 isMarked (ReadWriteHandle fp m b) = b
478 BlockBuffering Nothing -> -2
479 BlockBuffering (Just n) -> n
481 #ifndef __PARALLEL_HASKELL__
482 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
484 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
486 hcon (ReadHandle _ _ _) = ReadHandle
487 hcon (WriteHandle _ _ _) = WriteHandle
488 hcon (AppendHandle _ _ _) = AppendHandle
489 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
492 Computation $flush hdl$ causes any items buffered for output in handle
493 {\em hdl} to be sent immediately to the operating system.
496 hFlush :: Handle -> IO ()
498 htype <- readHandle handle
500 ErrorHandle ioError -> do
501 writeHandle handle htype
504 writeHandle handle htype
505 ioe_closedHandle handle
506 SemiClosedHandle _ _ -> do
507 writeHandle handle htype
508 ioe_closedHandle handle
510 rc <- _ccall_ flushFile (filePtr other)
511 writeHandle handle (markHandle htype)
515 constructErrorAndFail "hFlush"
519 %*********************************************************
521 \subsection[Seeking]{Repositioning Handles}
523 %*********************************************************
526 data HandlePosn = HandlePosn Handle Int
528 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
529 deriving (Eq, Ord, Ix, Enum, Read, Show)
532 Computation $hGetPosn hdl$ returns the current I/O
533 position of {\em hdl} as an abstract position. Computation
534 $hSetPosn p$ sets the position of {\em hdl}
535 to a previously obtained position {\em p}.
538 hGetPosn :: Handle -> IO HandlePosn
540 htype <- readHandle handle
542 ErrorHandle ioError -> do
543 writeHandle handle htype
546 writeHandle handle htype
547 ioe_closedHandle handle
548 SemiClosedHandle _ _ -> do
549 writeHandle handle htype
550 ioe_closedHandle handle
552 posn <- _ccall_ getFilePosn (filePtr other)
553 writeHandle handle htype
555 return (HandlePosn handle posn)
557 constructErrorAndFail "hGetPosn"
559 hSetPosn :: HandlePosn -> IO ()
560 hSetPosn (HandlePosn handle posn) = do
561 htype <- readHandle handle
563 ErrorHandle ioError -> do
564 writeHandle handle htype
567 writeHandle handle htype
568 ioe_closedHandle handle
569 SemiClosedHandle _ _ -> do
570 writeHandle handle htype
571 ioe_closedHandle handle
572 AppendHandle _ _ _ -> do
573 writeHandle handle htype
574 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
576 rc <- _ccall_ setFilePosn (filePtr other) posn
577 writeHandle handle (markHandle htype)
581 constructErrorAndFail "hSetPosn"
584 Computation $hSeek hdl mode i$ sets the position of handle
585 {\em hdl} depending on $mode$. If {\em mode} is
587 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
588 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
589 the current position.
590 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
592 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
593 the beginning of the file.
596 Some handles may not be seekable $hIsSeekable$, or only support a
597 subset of the possible positioning operations (e.g. it may only be
598 possible to seek to the end of a tape, or to a positive offset from
599 the beginning or current position).
601 It is not possible to set a negative I/O position, or for a physical
602 file, an I/O position beyond the current end-of-file.
605 hSeek :: Handle -> SeekMode -> Integer -> IO ()
606 hSeek handle mode offset@(J# _ s# d#) = do
607 htype <- readHandle handle
609 ErrorHandle ioError -> do
610 writeHandle handle htype
613 writeHandle handle htype
614 ioe_closedHandle handle
615 SemiClosedHandle _ _ -> do
616 writeHandle handle htype
617 ioe_closedHandle handle
618 AppendHandle _ _ _ -> do
619 writeHandle handle htype
620 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
622 rc <- _ccall_ seekFile (filePtr other) whence (I# s#)
624 writeHandle handle (markHandle htype)
628 constructErrorAndFail "hSeek"
631 whence = case mode of
632 AbsoluteSeek -> ``SEEK_SET''
633 RelativeSeek -> ``SEEK_CUR''
634 SeekFromEnd -> ``SEEK_END''
637 %*********************************************************
639 \subsection[Query]{Handle Properties}
641 %*********************************************************
643 A number of operations return information about the properties of a
644 handle. Each of these operations returns $True$ if the
645 handle has the specified property, and $False$
648 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
649 {\em hdl} is not block-buffered. Otherwise it returns
650 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
651 $( Just n )$ for block-buffering of {\em n} bytes.
654 hIsOpen :: Handle -> IO Bool
656 htype <- readHandle handle
658 ErrorHandle ioError -> do
659 writeHandle handle htype
662 writeHandle handle htype
664 SemiClosedHandle _ _ -> do
665 writeHandle handle htype
668 writeHandle handle htype
671 hIsClosed :: Handle -> IO Bool
672 hIsClosed handle = do
673 htype <- readHandle handle
675 ErrorHandle ioError -> do
676 writeHandle handle htype
679 writeHandle handle htype
682 writeHandle handle htype
685 hIsReadable :: Handle -> IO Bool
686 hIsReadable handle = do
687 htype <- readHandle handle
689 ErrorHandle ioError -> do
690 writeHandle handle htype
693 writeHandle handle htype
694 ioe_closedHandle handle
695 SemiClosedHandle _ _ -> do
696 writeHandle handle htype
697 ioe_closedHandle handle
699 writeHandle handle htype
700 return (isReadable other)
702 isReadable (ReadHandle _ _ _) = True
703 isReadable (ReadWriteHandle _ _ _) = True
706 hIsWritable :: Handle -> IO Bool
707 hIsWritable handle = do
708 htype <- readHandle handle
710 ErrorHandle ioError -> do
711 writeHandle handle htype
714 writeHandle handle htype
715 ioe_closedHandle handle
716 SemiClosedHandle _ _ -> do
717 writeHandle handle htype
718 ioe_closedHandle handle
720 writeHandle handle htype
721 return (isWritable other)
723 isWritable (AppendHandle _ _ _) = True
724 isWritable (WriteHandle _ _ _) = True
725 isWritable (ReadWriteHandle _ _ _) = True
728 getBufferMode :: Handle__ -> IO Handle__
729 getBufferMode htype =
730 case bufferMode htype of
731 Just x -> return htype
733 rc <- _ccall_ getBufferMode (filePtr htype)
737 0 -> Just NoBuffering
738 -1 -> Just LineBuffering
739 -2 -> Just (BlockBuffering Nothing)
741 n -> Just (BlockBuffering (Just n))
742 return (case htype of
743 ReadHandle fp _ b -> ReadHandle fp mode b
744 WriteHandle fp _ b -> WriteHandle fp mode b
745 AppendHandle fp _ b -> AppendHandle fp mode b
746 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
748 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
749 hIsBlockBuffered handle = do
750 htype <- readHandle handle
752 ErrorHandle ioError -> do
753 writeHandle handle htype
756 writeHandle handle htype
757 ioe_closedHandle handle
758 SemiClosedHandle _ _ -> do
759 writeHandle handle htype
760 ioe_closedHandle handle
762 other <- getBufferMode other
763 case bufferMode other of
764 Just (BlockBuffering size) -> do
765 writeHandle handle other
768 writeHandle handle other
769 return (False, Nothing)
771 constructErrorAndFail "hIsBlockBuffered"
773 hIsLineBuffered :: Handle -> IO Bool
774 hIsLineBuffered handle = do
775 htype <- readHandle handle
777 ErrorHandle ioError -> do
778 writeHandle handle htype
781 writeHandle handle htype
782 ioe_closedHandle handle
783 SemiClosedHandle _ _ -> do
784 writeHandle handle htype
785 ioe_closedHandle handle
787 other <- getBufferMode other
788 case bufferMode other of
789 Just LineBuffering -> do
790 writeHandle handle other
793 writeHandle handle other
796 constructErrorAndFail "hIsLineBuffered"
798 hIsNotBuffered :: Handle -> IO Bool
799 hIsNotBuffered handle = do
800 htype <- readHandle handle
802 ErrorHandle ioError -> do
803 writeHandle handle htype
806 writeHandle handle htype
807 ioe_closedHandle handle
808 SemiClosedHandle _ _ -> do
809 writeHandle handle htype
810 ioe_closedHandle handle
812 other <- getBufferMode other
813 case bufferMode other of
814 Just NoBuffering -> do
815 writeHandle handle other
818 writeHandle handle other
821 constructErrorAndFail "hIsNotBuffered"
823 hGetBuffering :: Handle -> IO BufferMode
824 hGetBuffering handle = do
825 htype <- readHandle handle
827 ErrorHandle ioError -> do
828 writeHandle handle htype
831 writeHandle handle htype
832 ioe_closedHandle handle
833 SemiClosedHandle _ _ -> do
834 writeHandle handle htype
835 ioe_closedHandle handle
837 other <- getBufferMode other
838 case bufferMode other of
840 writeHandle handle other
843 constructErrorAndFail "hGetBuffering"
845 hIsSeekable :: Handle -> IO Bool
846 hIsSeekable handle = do
847 htype <- readHandle handle
849 ErrorHandle ioError -> do
850 writeHandle handle htype
853 writeHandle handle htype
854 ioe_closedHandle handle
855 SemiClosedHandle _ _ -> do
856 writeHandle handle htype
857 ioe_closedHandle handle
858 AppendHandle _ _ _ -> do
859 writeHandle handle htype
862 rc <- _ccall_ seekFileP (filePtr other)
863 writeHandle handle htype
867 _ -> constructErrorAndFail "hIsSeekable"
871 %*********************************************************
873 \subsection{Miscellaneous}
875 %*********************************************************
877 These two functions are meant to get things out of @IOErrors@. They don't!
880 ioeGetFileName :: IOError -> Maybe FilePath
881 ioeGetErrorString :: IOError -> String
882 ioeGetHandle :: IOError -> Maybe Handle
884 ioeGetHandle (IOError h _ _) = h
885 ioeGetErrorString (IOError _ iot str) =
890 ioeGetFileName (IOError _ _ str) =
891 case span (/=':') str of
897 Internal function for creating an @IOError@ representing the
898 access of a closed file.
902 ioe_closedHandle :: Handle -> IO a
903 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")
906 A number of operations want to get at a readable or writeable handle, and fail
910 wantReadableHandle :: Handle -> IO Handle__
911 wantReadableHandle handle = do
912 htype <- readHandle handle
914 ErrorHandle ioError -> do
915 writeHandle handle htype
918 writeHandle handle htype
919 ioe_closedHandle handle
920 SemiClosedHandle _ _ -> do
921 writeHandle handle htype
922 ioe_closedHandle handle
923 AppendHandle _ _ _ -> do
924 writeHandle handle htype
925 fail (IOError (Just handle) IllegalOperation
926 "handle is not open for reading")
927 WriteHandle _ _ _ -> do
928 writeHandle handle htype
929 fail (IOError (Just handle) IllegalOperation
930 "handle is not open for reading")
931 other -> return other
933 wantWriteableHandle :: Handle
935 wantWriteableHandle handle = do
936 htype <- readHandle handle
938 ErrorHandle ioError -> do
939 writeHandle handle htype
942 writeHandle handle htype
943 ioe_closedHandle handle
944 SemiClosedHandle _ _ -> do
945 writeHandle handle htype
946 ioe_closedHandle handle
947 ReadHandle _ _ _ -> do
948 writeHandle handle htype
949 fail (IOError (Just handle) IllegalOperation "handle is not open for writing")
950 other -> return other