Use explicit language extensions & remove extension fields from base.cabal
[ghc-base.git] / Foreign / C / Error.hs
1 {-# LANGUAGE CPP, NoImplicitPrelude, ForeignFunctionInterface #-}
2 {-# OPTIONS_GHC -#include "HsBase.h" #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module      :  Foreign.C.Error
7 -- Copyright   :  (c) The FFI task force 2001
8 -- License     :  BSD-style (see the file libraries/base/LICENSE)
9 -- 
10 -- Maintainer  :  ffi@haskell.org
11 -- Stability   :  provisional
12 -- Portability :  portable
13 --
14 -- C-specific Marshalling support: Handling of C \"errno\" error codes.
15 --
16 -----------------------------------------------------------------------------
17
18 module Foreign.C.Error (
19
20   -- * Haskell representations of @errno@ values
21
22   Errno(..),            -- instance: Eq
23
24   -- ** Common @errno@ symbols
25   -- | Different operating systems and\/or C libraries often support
26   -- different values of @errno@.  This module defines the common values,
27   -- but due to the open definition of 'Errno' users may add definitions
28   -- which are not predefined.
29   eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, 
30   eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, 
31   eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, 
32   eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, 
33   eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, 
34   eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, 
35   eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, 
36   eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, 
37   eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, 
38   eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, 
39   ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, 
40   eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, 
41   eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, 
42   eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,
43
44   -- ** 'Errno' functions
45                         -- :: Errno
46   isValidErrno,         -- :: Errno -> Bool
47
48   -- access to the current thread's "errno" value
49   --
50   getErrno,             -- :: IO Errno
51   resetErrno,           -- :: IO ()
52
53   -- conversion of an "errno" value into IO error
54   --
55   errnoToIOError,       -- :: String       -- location
56                         -- -> Errno        -- errno
57                         -- -> Maybe Handle -- handle
58                         -- -> Maybe String -- filename
59                         -- -> IOError
60
61   -- throw current "errno" value
62   --
63   throwErrno,           -- ::                String               -> IO a
64
65   -- ** Guards for IO operations that may fail
66
67   throwErrnoIf,         -- :: (a -> Bool) -> String -> IO a       -> IO a
68   throwErrnoIf_,        -- :: (a -> Bool) -> String -> IO a       -> IO ()
69   throwErrnoIfRetry,    -- :: (a -> Bool) -> String -> IO a       -> IO a
70   throwErrnoIfRetry_,   -- :: (a -> Bool) -> String -> IO a       -> IO ()
71   throwErrnoIfMinus1,   -- :: Num a 
72                         -- =>                String -> IO a       -> IO a
73   throwErrnoIfMinus1_,  -- :: Num a 
74                         -- =>                String -> IO a       -> IO ()
75   throwErrnoIfMinus1Retry,
76                         -- :: Num a 
77                         -- =>                String -> IO a       -> IO a
78   throwErrnoIfMinus1Retry_,  
79                         -- :: Num a 
80                         -- =>                String -> IO a       -> IO ()
81   throwErrnoIfNull,     -- ::                String -> IO (Ptr a) -> IO (Ptr a)
82   throwErrnoIfNullRetry,-- ::                String -> IO (Ptr a) -> IO (Ptr a)
83
84   throwErrnoIfRetryMayBlock, 
85   throwErrnoIfRetryMayBlock_,
86   throwErrnoIfMinus1RetryMayBlock,
87   throwErrnoIfMinus1RetryMayBlock_,  
88   throwErrnoIfNullRetryMayBlock,
89
90   throwErrnoPath,
91   throwErrnoPathIf,
92   throwErrnoPathIf_,
93   throwErrnoPathIfNull,
94   throwErrnoPathIfMinus1,
95   throwErrnoPathIfMinus1_,
96 ) where
97
98
99 -- this is were we get the CONST_XXX definitions from that configure
100 -- calculated for us
101 --
102 #ifndef __NHC__
103 #include "HsBaseConfig.h"
104 #endif
105
106 import Foreign.Ptr
107 import Foreign.C.Types
108 import Foreign.C.String
109 import Foreign.Marshal.Error    ( void )
110 import Data.Maybe
111
112 #if __GLASGOW_HASKELL__
113 import GHC.IO
114 import GHC.IO.Exception
115 import GHC.IO.Handle.Types
116 import GHC.Num
117 import GHC.Base
118 #elif __HUGS__
119 import Hugs.Prelude             ( Handle, IOError, ioError )
120 import System.IO.Unsafe         ( unsafePerformIO )
121 #else
122 import System.IO                ( Handle )
123 import System.IO.Error          ( IOError, ioError )
124 import System.IO.Unsafe         ( unsafePerformIO )
125 import Foreign.Storable         ( Storable(poke,peek) )
126 #endif
127
128 #ifdef __HUGS__
129 {-# CFILES cbits/PrelIOUtils.c #-}
130 #endif
131
132
133 -- "errno" type
134 -- ------------
135
136 -- | Haskell representation for @errno@ values.
137 -- The implementation is deliberately exposed, to allow users to add
138 -- their own definitions of 'Errno' values.
139
140 newtype Errno = Errno CInt
141
142 instance Eq Errno where
143   errno1@(Errno no1) == errno2@(Errno no2) 
144     | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
145     | otherwise                                  = False
146
147 -- common "errno" symbols
148 --
149 eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, 
150   eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, 
151   eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, 
152   eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, 
153   eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, 
154   eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, 
155   eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, 
156   eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, 
157   eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, 
158   eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, 
159   ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, 
160   eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, 
161   eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, 
162   eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV                    :: Errno
163 --
164 -- the cCONST_XXX identifiers are cpp symbols whose value is computed by
165 -- configure 
166 --
167 eOK             = Errno 0
168 #ifdef __NHC__
169 #include "Errno.hs"
170 #else
171 e2BIG           = Errno (CONST_E2BIG)
172 eACCES          = Errno (CONST_EACCES)
173 eADDRINUSE      = Errno (CONST_EADDRINUSE)
174 eADDRNOTAVAIL   = Errno (CONST_EADDRNOTAVAIL)
175 eADV            = Errno (CONST_EADV)
176 eAFNOSUPPORT    = Errno (CONST_EAFNOSUPPORT)
177 eAGAIN          = Errno (CONST_EAGAIN)
178 eALREADY        = Errno (CONST_EALREADY)
179 eBADF           = Errno (CONST_EBADF)
180 eBADMSG         = Errno (CONST_EBADMSG)
181 eBADRPC         = Errno (CONST_EBADRPC)
182 eBUSY           = Errno (CONST_EBUSY)
183 eCHILD          = Errno (CONST_ECHILD)
184 eCOMM           = Errno (CONST_ECOMM)
185 eCONNABORTED    = Errno (CONST_ECONNABORTED)
186 eCONNREFUSED    = Errno (CONST_ECONNREFUSED)
187 eCONNRESET      = Errno (CONST_ECONNRESET)
188 eDEADLK         = Errno (CONST_EDEADLK)
189 eDESTADDRREQ    = Errno (CONST_EDESTADDRREQ)
190 eDIRTY          = Errno (CONST_EDIRTY)
191 eDOM            = Errno (CONST_EDOM)
192 eDQUOT          = Errno (CONST_EDQUOT)
193 eEXIST          = Errno (CONST_EEXIST)
194 eFAULT          = Errno (CONST_EFAULT)
195 eFBIG           = Errno (CONST_EFBIG)
196 eFTYPE          = Errno (CONST_EFTYPE)
197 eHOSTDOWN       = Errno (CONST_EHOSTDOWN)
198 eHOSTUNREACH    = Errno (CONST_EHOSTUNREACH)
199 eIDRM           = Errno (CONST_EIDRM)
200 eILSEQ          = Errno (CONST_EILSEQ)
201 eINPROGRESS     = Errno (CONST_EINPROGRESS)
202 eINTR           = Errno (CONST_EINTR)
203 eINVAL          = Errno (CONST_EINVAL)
204 eIO             = Errno (CONST_EIO)
205 eISCONN         = Errno (CONST_EISCONN)
206 eISDIR          = Errno (CONST_EISDIR)
207 eLOOP           = Errno (CONST_ELOOP)
208 eMFILE          = Errno (CONST_EMFILE)
209 eMLINK          = Errno (CONST_EMLINK)
210 eMSGSIZE        = Errno (CONST_EMSGSIZE)
211 eMULTIHOP       = Errno (CONST_EMULTIHOP)
212 eNAMETOOLONG    = Errno (CONST_ENAMETOOLONG)
213 eNETDOWN        = Errno (CONST_ENETDOWN)
214 eNETRESET       = Errno (CONST_ENETRESET)
215 eNETUNREACH     = Errno (CONST_ENETUNREACH)
216 eNFILE          = Errno (CONST_ENFILE)
217 eNOBUFS         = Errno (CONST_ENOBUFS)
218 eNODATA         = Errno (CONST_ENODATA)
219 eNODEV          = Errno (CONST_ENODEV)
220 eNOENT          = Errno (CONST_ENOENT)
221 eNOEXEC         = Errno (CONST_ENOEXEC)
222 eNOLCK          = Errno (CONST_ENOLCK)
223 eNOLINK         = Errno (CONST_ENOLINK)
224 eNOMEM          = Errno (CONST_ENOMEM)
225 eNOMSG          = Errno (CONST_ENOMSG)
226 eNONET          = Errno (CONST_ENONET)
227 eNOPROTOOPT     = Errno (CONST_ENOPROTOOPT)
228 eNOSPC          = Errno (CONST_ENOSPC)
229 eNOSR           = Errno (CONST_ENOSR)
230 eNOSTR          = Errno (CONST_ENOSTR)
231 eNOSYS          = Errno (CONST_ENOSYS)
232 eNOTBLK         = Errno (CONST_ENOTBLK)
233 eNOTCONN        = Errno (CONST_ENOTCONN)
234 eNOTDIR         = Errno (CONST_ENOTDIR)
235 eNOTEMPTY       = Errno (CONST_ENOTEMPTY)
236 eNOTSOCK        = Errno (CONST_ENOTSOCK)
237 eNOTTY          = Errno (CONST_ENOTTY)
238 eNXIO           = Errno (CONST_ENXIO)
239 eOPNOTSUPP      = Errno (CONST_EOPNOTSUPP)
240 ePERM           = Errno (CONST_EPERM)
241 ePFNOSUPPORT    = Errno (CONST_EPFNOSUPPORT)
242 ePIPE           = Errno (CONST_EPIPE)
243 ePROCLIM        = Errno (CONST_EPROCLIM)
244 ePROCUNAVAIL    = Errno (CONST_EPROCUNAVAIL)
245 ePROGMISMATCH   = Errno (CONST_EPROGMISMATCH)
246 ePROGUNAVAIL    = Errno (CONST_EPROGUNAVAIL)
247 ePROTO          = Errno (CONST_EPROTO)
248 ePROTONOSUPPORT = Errno (CONST_EPROTONOSUPPORT)
249 ePROTOTYPE      = Errno (CONST_EPROTOTYPE)
250 eRANGE          = Errno (CONST_ERANGE)
251 eREMCHG         = Errno (CONST_EREMCHG)
252 eREMOTE         = Errno (CONST_EREMOTE)
253 eROFS           = Errno (CONST_EROFS)
254 eRPCMISMATCH    = Errno (CONST_ERPCMISMATCH)
255 eRREMOTE        = Errno (CONST_ERREMOTE)
256 eSHUTDOWN       = Errno (CONST_ESHUTDOWN)
257 eSOCKTNOSUPPORT = Errno (CONST_ESOCKTNOSUPPORT)
258 eSPIPE          = Errno (CONST_ESPIPE)
259 eSRCH           = Errno (CONST_ESRCH)
260 eSRMNT          = Errno (CONST_ESRMNT)
261 eSTALE          = Errno (CONST_ESTALE)
262 eTIME           = Errno (CONST_ETIME)
263 eTIMEDOUT       = Errno (CONST_ETIMEDOUT)
264 eTOOMANYREFS    = Errno (CONST_ETOOMANYREFS)
265 eTXTBSY         = Errno (CONST_ETXTBSY)
266 eUSERS          = Errno (CONST_EUSERS)
267 eWOULDBLOCK     = Errno (CONST_EWOULDBLOCK)
268 eXDEV           = Errno (CONST_EXDEV)
269 #endif
270
271 -- | Yield 'True' if the given 'Errno' value is valid on the system.
272 -- This implies that the 'Eq' instance of 'Errno' is also system dependent
273 -- as it is only defined for valid values of 'Errno'.
274 --
275 isValidErrno               :: Errno -> Bool
276 --
277 -- the configure script sets all invalid "errno"s to -1
278 --
279 isValidErrno (Errno errno)  = errno /= -1
280
281
282 -- access to the current thread's "errno" value
283 -- --------------------------------------------
284
285 -- | Get the current value of @errno@ in the current thread.
286 --
287 getErrno :: IO Errno
288
289 -- We must call a C function to get the value of errno in general.  On
290 -- threaded systems, errno is hidden behind a C macro so that each OS
291 -- thread gets its own copy.
292 #ifdef __NHC__
293 getErrno = do e <- peek _errno; return (Errno e)
294 foreign import ccall unsafe "errno.h &errno" _errno :: Ptr CInt
295 #else
296 getErrno = do e <- get_errno; return (Errno e)
297 foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO CInt
298 #endif
299
300 -- | Reset the current thread\'s @errno@ value to 'eOK'.
301 --
302 resetErrno :: IO ()
303
304 -- Again, setting errno has to be done via a C function.
305 #ifdef __NHC__
306 resetErrno = poke _errno 0
307 #else
308 resetErrno = set_errno 0
309 foreign import ccall unsafe "HsBase.h __hscore_set_errno" set_errno :: CInt -> IO ()
310 #endif
311
312 -- throw current "errno" value
313 -- ---------------------------
314
315 -- | Throw an 'IOError' corresponding to the current value of 'getErrno'.
316 --
317 throwErrno     :: String        -- ^ textual description of the error location
318                -> IO a
319 throwErrno loc  =
320   do
321     errno <- getErrno
322     ioError (errnoToIOError loc errno Nothing Nothing)
323
324
325 -- guards for IO operations that may fail
326 -- --------------------------------------
327
328 -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
329 -- if the result value of the 'IO' action meets the given predicate.
330 --
331 throwErrnoIf    :: (a -> Bool)  -- ^ predicate to apply to the result value
332                                 -- of the 'IO' operation
333                 -> String       -- ^ textual description of the location
334                 -> IO a         -- ^ the 'IO' operation to be executed
335                 -> IO a
336 throwErrnoIf pred loc f  = 
337   do
338     res <- f
339     if pred res then throwErrno loc else return res
340
341 -- | as 'throwErrnoIf', but discards the result of the 'IO' action after
342 -- error handling.
343 --
344 throwErrnoIf_   :: (a -> Bool) -> String -> IO a -> IO ()
345 throwErrnoIf_ pred loc f  = void $ throwErrnoIf pred loc f
346
347 -- | as 'throwErrnoIf', but retry the 'IO' action when it yields the
348 -- error code 'eINTR' - this amounts to the standard retry loop for
349 -- interrupted POSIX system calls.
350 --
351 throwErrnoIfRetry            :: (a -> Bool) -> String -> IO a -> IO a
352 throwErrnoIfRetry pred loc f  = 
353   do
354     res <- f
355     if pred res
356       then do
357         err <- getErrno
358         if err == eINTR
359           then throwErrnoIfRetry pred loc f
360           else throwErrno loc
361       else return res
362
363 -- | as 'throwErrnoIfRetry', but additionally if the operation 
364 -- yields the error code 'eAGAIN' or 'eWOULDBLOCK', an alternative
365 -- action is executed before retrying.
366 --
367 throwErrnoIfRetryMayBlock
368                 :: (a -> Bool)  -- ^ predicate to apply to the result value
369                                 -- of the 'IO' operation
370                 -> String       -- ^ textual description of the location
371                 -> IO a         -- ^ the 'IO' operation to be executed
372                 -> IO b         -- ^ action to execute before retrying if
373                                 -- an immediate retry would block
374                 -> IO a
375 throwErrnoIfRetryMayBlock pred loc f on_block  = 
376   do
377     res <- f
378     if pred res
379       then do
380         err <- getErrno
381         if err == eINTR
382           then throwErrnoIfRetryMayBlock pred loc f on_block
383           else if err == eWOULDBLOCK || err == eAGAIN
384                  then do _ <- on_block
385                          throwErrnoIfRetryMayBlock pred loc f on_block
386                  else throwErrno loc
387       else return res
388
389 -- | as 'throwErrnoIfRetry', but discards the result.
390 --
391 throwErrnoIfRetry_            :: (a -> Bool) -> String -> IO a -> IO ()
392 throwErrnoIfRetry_ pred loc f  = void $ throwErrnoIfRetry pred loc f
393
394 -- | as 'throwErrnoIfRetryMayBlock', but discards the result.
395 --
396 throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO ()
397 throwErrnoIfRetryMayBlock_ pred loc f on_block 
398   = void $ throwErrnoIfRetryMayBlock pred loc f on_block
399
400 -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
401 -- if the 'IO' action returns a result of @-1@.
402 --
403 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
404 throwErrnoIfMinus1  = throwErrnoIf (== -1)
405
406 -- | as 'throwErrnoIfMinus1', but discards the result.
407 --
408 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
409 throwErrnoIfMinus1_  = throwErrnoIf_ (== -1)
410
411 -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
412 -- if the 'IO' action returns a result of @-1@, but retries in case of
413 -- an interrupted operation.
414 --
415 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
416 throwErrnoIfMinus1Retry  = throwErrnoIfRetry (== -1)
417
418 -- | as 'throwErrnoIfMinus1', but discards the result.
419 --
420 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
421 throwErrnoIfMinus1Retry_  = throwErrnoIfRetry_ (== -1)
422
423 -- | as 'throwErrnoIfMinus1Retry', but checks for operations that would block.
424 --
425 throwErrnoIfMinus1RetryMayBlock :: Num a => String -> IO a -> IO b -> IO a
426 throwErrnoIfMinus1RetryMayBlock  = throwErrnoIfRetryMayBlock (== -1)
427
428 -- | as 'throwErrnoIfMinus1RetryMayBlock', but discards the result.
429 --
430 throwErrnoIfMinus1RetryMayBlock_ :: Num a => String -> IO a -> IO b -> IO ()
431 throwErrnoIfMinus1RetryMayBlock_  = throwErrnoIfRetryMayBlock_ (== -1)
432
433 -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
434 -- if the 'IO' action returns 'nullPtr'.
435 --
436 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
437 throwErrnoIfNull  = throwErrnoIf (== nullPtr)
438
439 -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
440 -- if the 'IO' action returns 'nullPtr',
441 -- but retry in case of an interrupted operation.
442 --
443 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
444 throwErrnoIfNullRetry  = throwErrnoIfRetry (== nullPtr)
445
446 -- | as 'throwErrnoIfNullRetry', but checks for operations that would block.
447 --
448 throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)
449 throwErrnoIfNullRetryMayBlock  = throwErrnoIfRetryMayBlock (== nullPtr)
450
451 -- | as 'throwErrno', but exceptions include the given path when appropriate.
452 --
453 throwErrnoPath :: String -> FilePath -> IO a
454 throwErrnoPath loc path =
455   do
456     errno <- getErrno
457     ioError (errnoToIOError loc errno Nothing (Just path))
458
459 -- | as 'throwErrnoIf', but exceptions include the given path when
460 --   appropriate.
461 --
462 throwErrnoPathIf :: (a -> Bool) -> String -> FilePath -> IO a -> IO a
463 throwErrnoPathIf pred loc path f =
464   do
465     res <- f
466     if pred res then throwErrnoPath loc path else return res
467
468 -- | as 'throwErrnoIf_', but exceptions include the given path when
469 --   appropriate.
470 --
471 throwErrnoPathIf_ :: (a -> Bool) -> String -> FilePath -> IO a -> IO ()
472 throwErrnoPathIf_ pred loc path f  = void $ throwErrnoPathIf pred loc path f
473
474 -- | as 'throwErrnoIfNull', but exceptions include the given path when
475 --   appropriate.
476 --
477 throwErrnoPathIfNull :: String -> FilePath -> IO (Ptr a) -> IO (Ptr a)
478 throwErrnoPathIfNull  = throwErrnoPathIf (== nullPtr)
479
480 -- | as 'throwErrnoIfMinus1', but exceptions include the given path when
481 --   appropriate.
482 --
483 throwErrnoPathIfMinus1 :: Num a => String -> FilePath -> IO a -> IO a
484 throwErrnoPathIfMinus1 = throwErrnoPathIf (== -1)
485
486 -- | as 'throwErrnoIfMinus1_', but exceptions include the given path when
487 --   appropriate.
488 --
489 throwErrnoPathIfMinus1_ :: Num a => String -> FilePath -> IO a -> IO ()
490 throwErrnoPathIfMinus1_  = throwErrnoPathIf_ (== -1)
491
492 -- conversion of an "errno" value into IO error
493 -- --------------------------------------------
494
495 -- | Construct an 'IOError' based on the given 'Errno' value.
496 -- The optional information can be used to improve the accuracy of
497 -- error messages.
498 --
499 errnoToIOError  :: String       -- ^ the location where the error occurred
500                 -> Errno        -- ^ the error number
501                 -> Maybe Handle -- ^ optional handle associated with the error
502                 -> Maybe String -- ^ optional filename associated with the error
503                 -> IOError
504 errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do
505     str <- strerror errno >>= peekCString
506 #if __GLASGOW_HASKELL__
507     return (IOError maybeHdl errType loc str (Just errno') maybeName)
508     where
509     Errno errno' = errno
510     errType
511         | errno == eOK             = OtherError
512         | errno == e2BIG           = ResourceExhausted
513         | errno == eACCES          = PermissionDenied
514         | errno == eADDRINUSE      = ResourceBusy
515         | errno == eADDRNOTAVAIL   = UnsupportedOperation
516         | errno == eADV            = OtherError
517         | errno == eAFNOSUPPORT    = UnsupportedOperation
518         | errno == eAGAIN          = ResourceExhausted
519         | errno == eALREADY        = AlreadyExists
520         | errno == eBADF           = InvalidArgument
521         | errno == eBADMSG         = InappropriateType
522         | errno == eBADRPC         = OtherError
523         | errno == eBUSY           = ResourceBusy
524         | errno == eCHILD          = NoSuchThing
525         | errno == eCOMM           = ResourceVanished
526         | errno == eCONNABORTED    = OtherError
527         | errno == eCONNREFUSED    = NoSuchThing
528         | errno == eCONNRESET      = ResourceVanished
529         | errno == eDEADLK         = ResourceBusy
530         | errno == eDESTADDRREQ    = InvalidArgument
531         | errno == eDIRTY          = UnsatisfiedConstraints
532         | errno == eDOM            = InvalidArgument
533         | errno == eDQUOT          = PermissionDenied
534         | errno == eEXIST          = AlreadyExists
535         | errno == eFAULT          = OtherError
536         | errno == eFBIG           = PermissionDenied
537         | errno == eFTYPE          = InappropriateType
538         | errno == eHOSTDOWN       = NoSuchThing
539         | errno == eHOSTUNREACH    = NoSuchThing
540         | errno == eIDRM           = ResourceVanished
541         | errno == eILSEQ          = InvalidArgument
542         | errno == eINPROGRESS     = AlreadyExists
543         | errno == eINTR           = Interrupted
544         | errno == eINVAL          = InvalidArgument
545         | errno == eIO             = HardwareFault
546         | errno == eISCONN         = AlreadyExists
547         | errno == eISDIR          = InappropriateType
548         | errno == eLOOP           = InvalidArgument
549         | errno == eMFILE          = ResourceExhausted
550         | errno == eMLINK          = ResourceExhausted
551         | errno == eMSGSIZE        = ResourceExhausted
552         | errno == eMULTIHOP       = UnsupportedOperation
553         | errno == eNAMETOOLONG    = InvalidArgument
554         | errno == eNETDOWN        = ResourceVanished
555         | errno == eNETRESET       = ResourceVanished
556         | errno == eNETUNREACH     = NoSuchThing
557         | errno == eNFILE          = ResourceExhausted
558         | errno == eNOBUFS         = ResourceExhausted
559         | errno == eNODATA         = NoSuchThing
560         | errno == eNODEV          = UnsupportedOperation
561         | errno == eNOENT          = NoSuchThing
562         | errno == eNOEXEC         = InvalidArgument
563         | errno == eNOLCK          = ResourceExhausted
564         | errno == eNOLINK         = ResourceVanished
565         | errno == eNOMEM          = ResourceExhausted
566         | errno == eNOMSG          = NoSuchThing
567         | errno == eNONET          = NoSuchThing
568         | errno == eNOPROTOOPT     = UnsupportedOperation
569         | errno == eNOSPC          = ResourceExhausted
570         | errno == eNOSR           = ResourceExhausted
571         | errno == eNOSTR          = InvalidArgument
572         | errno == eNOSYS          = UnsupportedOperation
573         | errno == eNOTBLK         = InvalidArgument
574         | errno == eNOTCONN        = InvalidArgument
575         | errno == eNOTDIR         = InappropriateType
576         | errno == eNOTEMPTY       = UnsatisfiedConstraints
577         | errno == eNOTSOCK        = InvalidArgument
578         | errno == eNOTTY          = IllegalOperation
579         | errno == eNXIO           = NoSuchThing
580         | errno == eOPNOTSUPP      = UnsupportedOperation
581         | errno == ePERM           = PermissionDenied
582         | errno == ePFNOSUPPORT    = UnsupportedOperation
583         | errno == ePIPE           = ResourceVanished
584         | errno == ePROCLIM        = PermissionDenied
585         | errno == ePROCUNAVAIL    = UnsupportedOperation
586         | errno == ePROGMISMATCH   = ProtocolError
587         | errno == ePROGUNAVAIL    = UnsupportedOperation
588         | errno == ePROTO          = ProtocolError
589         | errno == ePROTONOSUPPORT = ProtocolError
590         | errno == ePROTOTYPE      = ProtocolError
591         | errno == eRANGE          = UnsupportedOperation
592         | errno == eREMCHG         = ResourceVanished
593         | errno == eREMOTE         = IllegalOperation
594         | errno == eROFS           = PermissionDenied
595         | errno == eRPCMISMATCH    = ProtocolError
596         | errno == eRREMOTE        = IllegalOperation
597         | errno == eSHUTDOWN       = IllegalOperation
598         | errno == eSOCKTNOSUPPORT = UnsupportedOperation
599         | errno == eSPIPE          = UnsupportedOperation
600         | errno == eSRCH           = NoSuchThing
601         | errno == eSRMNT          = UnsatisfiedConstraints
602         | errno == eSTALE          = ResourceVanished
603         | errno == eTIME           = TimeExpired
604         | errno == eTIMEDOUT       = TimeExpired
605         | errno == eTOOMANYREFS    = ResourceExhausted
606         | errno == eTXTBSY         = ResourceBusy
607         | errno == eUSERS          = ResourceExhausted
608         | errno == eWOULDBLOCK     = OtherError
609         | errno == eXDEV           = UnsupportedOperation
610         | otherwise                = OtherError
611 #else
612     return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
613 #endif
614
615 foreign import ccall unsafe "string.h" strerror :: Errno -> IO (Ptr CChar)