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