[project @ 2002-09-25 15:24:07 by simonmar]
[ghc-base.git] / Foreign / C / Error.hs
1 {-# OPTIONS -fno-implicit-prelude -#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 representation for "errno" values
19   --
20   Errno(..),            -- instance: Eq
21   eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, 
22   eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, 
23   eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, 
24   eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, 
25   eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, 
26   eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, 
27   eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, 
28   eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, 
29   eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, 
30   eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, 
31   ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, 
32   eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, 
33   eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, 
34   eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,
35                         -- :: Errno
36   isValidErrno,         -- :: Errno -> Bool
37
38   -- access to the current thread's "errno" value
39   --
40   getErrno,             -- :: IO Errno
41   resetErrno,           -- :: IO ()
42
43   -- conversion of an "errno" value into IO error
44   --
45   errnoToIOError,       -- :: String       -- location
46                         -- -> Errno        -- errno
47                         -- -> Maybe Handle -- handle
48                         -- -> Maybe String -- filename
49                         -- -> IOError
50
51   -- throw current "errno" value
52   --
53   throwErrno,           -- ::                String               -> IO a
54
55   -- guards for IO operations that may fail
56   --
57   throwErrnoIf,         -- :: (a -> Bool) -> String -> IO a       -> IO a
58   throwErrnoIf_,        -- :: (a -> Bool) -> String -> IO a       -> IO ()
59   throwErrnoIfRetry,    -- :: (a -> Bool) -> String -> IO a       -> IO a
60   throwErrnoIfRetry_,   -- :: (a -> Bool) -> String -> IO a       -> IO ()
61   throwErrnoIfMinus1,   -- :: Num a 
62                         -- =>                String -> IO a       -> IO a
63   throwErrnoIfMinus1_,  -- :: Num a 
64                         -- =>                String -> IO a       -> IO ()
65   throwErrnoIfMinus1Retry,  
66                         -- :: Num a 
67                         -- =>                String -> IO a       -> IO a
68   throwErrnoIfMinus1Retry_,  
69                         -- :: Num a 
70                         -- =>                String -> IO a       -> IO ()
71   throwErrnoIfNull,     -- ::                String -> IO (Ptr a) -> IO (Ptr a)
72   throwErrnoIfNullRetry,-- ::                String -> IO (Ptr a) -> IO (Ptr a)
73
74   throwErrnoIfRetryMayBlock, 
75   throwErrnoIfRetryMayBlock_,
76   throwErrnoIfMinus1RetryMayBlock,
77   throwErrnoIfMinus1RetryMayBlock_,  
78   throwErrnoIfNullRetryMayBlock
79 ) where
80
81
82 -- this is were we get the CCONST_XXX definitions from that configure
83 -- calculated for us
84 --
85 #include "config.h"
86
87 -- system dependent imports
88 -- ------------------------
89
90 -- GHC allows us to get at the guts inside IO errors/exceptions
91 --
92 #if __GLASGOW_HASKELL__
93 import GHC.IOBase (Exception(..), IOException(..), IOErrorType(..))
94 #endif /* __GLASGOW_HASKELL__ */
95
96
97 -- regular imports
98 -- ---------------
99
100 import Foreign.Storable
101 import Foreign.Ptr
102 import Foreign.C.Types
103 import Foreign.C.String
104 import Foreign.Marshal.Error    ( void )
105 import Data.Maybe
106
107 #if __GLASGOW_HASKELL__
108 import GHC.Storable
109 import GHC.IOBase
110 import GHC.Num
111 import GHC.Base
112 #else
113 import System.IO                ( IOError, Handle, ioError )
114 import System.IO.Unsafe         ( unsafePerformIO )
115 #endif
116
117 -- "errno" type
118 -- ------------
119
120 -- import of C function that gives address of errno
121 -- This function exists because errno is a variable on some systems, but on
122 -- Windows it is a macro for a function...
123 -- [yes, global variables and thread safety don't really go hand-in-hand. -- sof]
124 foreign import ccall unsafe "HsBase.h ghcErrno" _errno :: Ptr CInt
125
126 -- Haskell representation for "errno" values
127 --
128 newtype Errno = Errno CInt
129
130 instance Eq Errno where
131   errno1@(Errno no1) == errno2@(Errno no2) 
132     | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
133     | otherwise                                  = False
134
135 -- common "errno" symbols
136 --
137 eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, 
138   eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, 
139   eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, 
140   eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, 
141   eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, 
142   eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, 
143   eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, 
144   eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, 
145   eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, 
146   eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, 
147   ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, 
148   eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, 
149   eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, 
150   eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV                    :: Errno
151 --
152 -- the cCONST_XXX identifiers are cpp symbols whose value is computed by
153 -- configure 
154 --
155 eOK             = Errno 0
156 e2BIG           = Errno (CCONST_E2BIG)
157 eACCES          = Errno (CCONST_EACCES)
158 eADDRINUSE      = Errno (CCONST_EADDRINUSE)
159 eADDRNOTAVAIL   = Errno (CCONST_EADDRNOTAVAIL)
160 eADV            = Errno (CCONST_EADV)
161 eAFNOSUPPORT    = Errno (CCONST_EAFNOSUPPORT)
162 eAGAIN          = Errno (CCONST_EAGAIN)
163 eALREADY        = Errno (CCONST_EALREADY)
164 eBADF           = Errno (CCONST_EBADF)
165 eBADMSG         = Errno (CCONST_EBADMSG)
166 eBADRPC         = Errno (CCONST_EBADRPC)
167 eBUSY           = Errno (CCONST_EBUSY)
168 eCHILD          = Errno (CCONST_ECHILD)
169 eCOMM           = Errno (CCONST_ECOMM)
170 eCONNABORTED    = Errno (CCONST_ECONNABORTED)
171 eCONNREFUSED    = Errno (CCONST_ECONNREFUSED)
172 eCONNRESET      = Errno (CCONST_ECONNRESET)
173 eDEADLK         = Errno (CCONST_EDEADLK)
174 eDESTADDRREQ    = Errno (CCONST_EDESTADDRREQ)
175 eDIRTY          = Errno (CCONST_EDIRTY)
176 eDOM            = Errno (CCONST_EDOM)
177 eDQUOT          = Errno (CCONST_EDQUOT)
178 eEXIST          = Errno (CCONST_EEXIST)
179 eFAULT          = Errno (CCONST_EFAULT)
180 eFBIG           = Errno (CCONST_EFBIG)
181 eFTYPE          = Errno (CCONST_EFTYPE)
182 eHOSTDOWN       = Errno (CCONST_EHOSTDOWN)
183 eHOSTUNREACH    = Errno (CCONST_EHOSTUNREACH)
184 eIDRM           = Errno (CCONST_EIDRM)
185 eILSEQ          = Errno (CCONST_EILSEQ)
186 eINPROGRESS     = Errno (CCONST_EINPROGRESS)
187 eINTR           = Errno (CCONST_EINTR)
188 eINVAL          = Errno (CCONST_EINVAL)
189 eIO             = Errno (CCONST_EIO)
190 eISCONN         = Errno (CCONST_EISCONN)
191 eISDIR          = Errno (CCONST_EISDIR)
192 eLOOP           = Errno (CCONST_ELOOP)
193 eMFILE          = Errno (CCONST_EMFILE)
194 eMLINK          = Errno (CCONST_EMLINK)
195 eMSGSIZE        = Errno (CCONST_EMSGSIZE)
196 eMULTIHOP       = Errno (CCONST_EMULTIHOP)
197 eNAMETOOLONG    = Errno (CCONST_ENAMETOOLONG)
198 eNETDOWN        = Errno (CCONST_ENETDOWN)
199 eNETRESET       = Errno (CCONST_ENETRESET)
200 eNETUNREACH     = Errno (CCONST_ENETUNREACH)
201 eNFILE          = Errno (CCONST_ENFILE)
202 eNOBUFS         = Errno (CCONST_ENOBUFS)
203 eNODATA         = Errno (CCONST_ENODATA)
204 eNODEV          = Errno (CCONST_ENODEV)
205 eNOENT          = Errno (CCONST_ENOENT)
206 eNOEXEC         = Errno (CCONST_ENOEXEC)
207 eNOLCK          = Errno (CCONST_ENOLCK)
208 eNOLINK         = Errno (CCONST_ENOLINK)
209 eNOMEM          = Errno (CCONST_ENOMEM)
210 eNOMSG          = Errno (CCONST_ENOMSG)
211 eNONET          = Errno (CCONST_ENONET)
212 eNOPROTOOPT     = Errno (CCONST_ENOPROTOOPT)
213 eNOSPC          = Errno (CCONST_ENOSPC)
214 eNOSR           = Errno (CCONST_ENOSR)
215 eNOSTR          = Errno (CCONST_ENOSTR)
216 eNOSYS          = Errno (CCONST_ENOSYS)
217 eNOTBLK         = Errno (CCONST_ENOTBLK)
218 eNOTCONN        = Errno (CCONST_ENOTCONN)
219 eNOTDIR         = Errno (CCONST_ENOTDIR)
220 eNOTEMPTY       = Errno (CCONST_ENOTEMPTY)
221 eNOTSOCK        = Errno (CCONST_ENOTSOCK)
222 eNOTTY          = Errno (CCONST_ENOTTY)
223 eNXIO           = Errno (CCONST_ENXIO)
224 eOPNOTSUPP      = Errno (CCONST_EOPNOTSUPP)
225 ePERM           = Errno (CCONST_EPERM)
226 ePFNOSUPPORT    = Errno (CCONST_EPFNOSUPPORT)
227 ePIPE           = Errno (CCONST_EPIPE)
228 ePROCLIM        = Errno (CCONST_EPROCLIM)
229 ePROCUNAVAIL    = Errno (CCONST_EPROCUNAVAIL)
230 ePROGMISMATCH   = Errno (CCONST_EPROGMISMATCH)
231 ePROGUNAVAIL    = Errno (CCONST_EPROGUNAVAIL)
232 ePROTO          = Errno (CCONST_EPROTO)
233 ePROTONOSUPPORT = Errno (CCONST_EPROTONOSUPPORT)
234 ePROTOTYPE      = Errno (CCONST_EPROTOTYPE)
235 eRANGE          = Errno (CCONST_ERANGE)
236 eREMCHG         = Errno (CCONST_EREMCHG)
237 eREMOTE         = Errno (CCONST_EREMOTE)
238 eROFS           = Errno (CCONST_EROFS)
239 eRPCMISMATCH    = Errno (CCONST_ERPCMISMATCH)
240 eRREMOTE        = Errno (CCONST_ERREMOTE)
241 eSHUTDOWN       = Errno (CCONST_ESHUTDOWN)
242 eSOCKTNOSUPPORT = Errno (CCONST_ESOCKTNOSUPPORT)
243 eSPIPE          = Errno (CCONST_ESPIPE)
244 eSRCH           = Errno (CCONST_ESRCH)
245 eSRMNT          = Errno (CCONST_ESRMNT)
246 eSTALE          = Errno (CCONST_ESTALE)
247 eTIME           = Errno (CCONST_ETIME)
248 eTIMEDOUT       = Errno (CCONST_ETIMEDOUT)
249 eTOOMANYREFS    = Errno (CCONST_ETOOMANYREFS)
250 eTXTBSY         = Errno (CCONST_ETXTBSY)
251 eUSERS          = Errno (CCONST_EUSERS)
252 eWOULDBLOCK     = Errno (CCONST_EWOULDBLOCK)
253 eXDEV           = Errno (CCONST_EXDEV)
254
255 -- checks whether the given errno value is supported on the current
256 -- architecture
257 --
258 isValidErrno               :: Errno -> Bool
259 --
260 -- the configure script sets all invalid "errno"s to -1
261 --
262 isValidErrno (Errno errno)  = errno /= -1
263
264
265 -- access to the current thread's "errno" value
266 -- --------------------------------------------
267
268 -- yield the current thread's "errno" value
269 --
270 getErrno :: IO Errno
271 getErrno  = do e <- peek _errno; return (Errno e)
272
273 -- set the current thread's "errno" value to 0
274 --
275 resetErrno :: IO ()
276 resetErrno  = poke _errno 0
277
278
279 -- throw current "errno" value
280 -- ---------------------------
281
282 -- the common case: throw an IO error based on a textual description
283 -- of the error location and the current thread's "errno" value
284 --
285 throwErrno     :: String -> IO a
286 throwErrno loc  =
287   do
288     errno <- getErrno
289     ioError (errnoToIOError loc errno Nothing Nothing)
290
291
292 -- guards for IO operations that may fail
293 -- --------------------------------------
294
295 -- guard an IO operation and throw an "errno" based exception of the result
296 -- value of the IO operation meets the given predicate
297 --
298 throwErrnoIf            :: (a -> Bool) -> String -> IO a -> IO a
299 throwErrnoIf pred loc f  = 
300   do
301     res <- f
302     if pred res then throwErrno loc else return res
303
304 -- as `throwErrnoIf', but discards the result
305 --
306 throwErrnoIf_            :: (a -> Bool) -> String -> IO a -> IO ()
307 throwErrnoIf_ pred loc f  = void $ throwErrnoIf pred loc f
308
309 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
310 -- flag `EINTR')
311 --
312 throwErrnoIfRetry            :: (a -> Bool) -> String -> IO a -> IO a
313 throwErrnoIfRetry pred loc f  = 
314   do
315     res <- f
316     if pred res
317       then do
318         err <- getErrno
319         if err == eINTR
320           then throwErrnoIfRetry pred loc f
321           else throwErrno loc
322       else return res
323
324 -- as `throwErrnoIfRetry', but checks for operations that would block and
325 -- executes an alternative action in that case.
326
327 throwErrnoIfRetryMayBlock  :: (a -> Bool) -> String -> IO a -> IO b -> IO a
328 throwErrnoIfRetryMayBlock pred loc f on_block  = 
329   do
330     res <- f
331     if pred res
332       then do
333         err <- getErrno
334         if err == eINTR
335           then throwErrnoIfRetryMayBlock pred loc f on_block
336           else if err == eWOULDBLOCK || err == eAGAIN
337                  then do on_block; throwErrnoIfRetryMayBlock pred loc f on_block
338                  else throwErrno loc
339       else return res
340
341 -- as `throwErrnoIfRetry', but discards the result
342 --
343 throwErrnoIfRetry_            :: (a -> Bool) -> String -> IO a -> IO ()
344 throwErrnoIfRetry_ pred loc f  = void $ throwErrnoIfRetry pred loc f
345
346 -- as `throwErrnoIfRetryMayBlock', but discards the result
347 --
348 throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO ()
349 throwErrnoIfRetryMayBlock_ pred loc f on_block 
350   = void $ throwErrnoIfRetryMayBlock pred loc f on_block
351
352 -- throws "errno" if a result of "-1" is returned
353 --
354 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
355 throwErrnoIfMinus1  = throwErrnoIf (== -1)
356
357 -- as `throwErrnoIfMinus1', but discards the result
358 --
359 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
360 throwErrnoIfMinus1_  = throwErrnoIf_ (== -1)
361
362 -- throws "errno" if a result of "-1" is returned, but retries in case of an
363 -- interrupted operation
364 --
365 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
366 throwErrnoIfMinus1Retry  = throwErrnoIfRetry (== -1)
367
368 -- as `throwErrnoIfMinus1', but discards the result
369 --
370 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
371 throwErrnoIfMinus1Retry_  = throwErrnoIfRetry_ (== -1)
372
373 -- as throwErrnoIfMinus1Retry, but checks for operations that would block
374 --
375 throwErrnoIfMinus1RetryMayBlock :: Num a => String -> IO a -> IO b -> IO a
376 throwErrnoIfMinus1RetryMayBlock  = throwErrnoIfRetryMayBlock (== -1)
377
378 -- as `throwErrnoIfMinus1RetryMayBlock', but discards the result
379 --
380 throwErrnoIfMinus1RetryMayBlock_ :: Num a => String -> IO a -> IO b -> IO ()
381 throwErrnoIfMinus1RetryMayBlock_  = throwErrnoIfRetryMayBlock_ (== -1)
382
383 -- throws "errno" if a result of a NULL pointer is returned
384 --
385 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
386 throwErrnoIfNull  = throwErrnoIf (== nullPtr)
387
388 -- throws "errno" if a result of a NULL pointer is returned, but retries in
389 -- case of an interrupted operation
390 --
391 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
392 throwErrnoIfNullRetry  = throwErrnoIfRetry (== nullPtr)
393
394 -- as throwErrnoIfNullRetry, but checks for operations that would block
395 --
396 throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)
397 throwErrnoIfNullRetryMayBlock  = throwErrnoIfRetryMayBlock (== nullPtr)
398
399 -- conversion of an "errno" value into IO error
400 -- --------------------------------------------
401
402 -- convert a location string, an "errno" value, an optional handle,
403 -- and an optional filename into a matching IO error
404 --
405 errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
406 errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do
407     str <- strerror errno >>= peekCString
408 #if __GLASGOW_HASKELL__
409     return (IOException (IOError maybeHdl errType loc str maybeName))
410     where
411     errType
412         | errno == eOK             = OtherError
413         | errno == e2BIG           = ResourceExhausted
414         | errno == eACCES          = PermissionDenied
415         | errno == eADDRINUSE      = ResourceBusy
416         | errno == eADDRNOTAVAIL   = UnsupportedOperation
417         | errno == eADV            = OtherError
418         | errno == eAFNOSUPPORT    = UnsupportedOperation
419         | errno == eAGAIN          = ResourceExhausted
420         | errno == eALREADY        = AlreadyExists
421         | errno == eBADF           = OtherError
422         | errno == eBADMSG         = InappropriateType
423         | errno == eBADRPC         = OtherError
424         | errno == eBUSY           = ResourceBusy
425         | errno == eCHILD          = NoSuchThing
426         | errno == eCOMM           = ResourceVanished
427         | errno == eCONNABORTED    = OtherError
428         | errno == eCONNREFUSED    = NoSuchThing
429         | errno == eCONNRESET      = ResourceVanished
430         | errno == eDEADLK         = ResourceBusy
431         | errno == eDESTADDRREQ    = InvalidArgument
432         | errno == eDIRTY          = UnsatisfiedConstraints
433         | errno == eDOM            = InvalidArgument
434         | errno == eDQUOT          = PermissionDenied
435         | errno == eEXIST          = AlreadyExists
436         | errno == eFAULT          = OtherError
437         | errno == eFBIG           = PermissionDenied
438         | errno == eFTYPE          = InappropriateType
439         | errno == eHOSTDOWN       = NoSuchThing
440         | errno == eHOSTUNREACH    = NoSuchThing
441         | errno == eIDRM           = ResourceVanished
442         | errno == eILSEQ          = InvalidArgument
443         | errno == eINPROGRESS     = AlreadyExists
444         | errno == eINTR           = Interrupted
445         | errno == eINVAL          = InvalidArgument
446         | errno == eIO             = HardwareFault
447         | errno == eISCONN         = AlreadyExists
448         | errno == eISDIR          = InappropriateType
449         | errno == eLOOP           = InvalidArgument
450         | errno == eMFILE          = ResourceExhausted
451         | errno == eMLINK          = ResourceExhausted
452         | errno == eMSGSIZE        = ResourceExhausted
453         | errno == eMULTIHOP       = UnsupportedOperation
454         | errno == eNAMETOOLONG    = InvalidArgument
455         | errno == eNETDOWN        = ResourceVanished
456         | errno == eNETRESET       = ResourceVanished
457         | errno == eNETUNREACH     = NoSuchThing
458         | errno == eNFILE          = ResourceExhausted
459         | errno == eNOBUFS         = ResourceExhausted
460         | errno == eNODATA         = NoSuchThing
461         | errno == eNODEV          = UnsupportedOperation
462         | errno == eNOENT          = NoSuchThing
463         | errno == eNOEXEC         = InvalidArgument
464         | errno == eNOLCK          = ResourceExhausted
465         | errno == eNOLINK         = ResourceVanished
466         | errno == eNOMEM          = ResourceExhausted
467         | errno == eNOMSG          = NoSuchThing
468         | errno == eNONET          = NoSuchThing
469         | errno == eNOPROTOOPT     = UnsupportedOperation
470         | errno == eNOSPC          = ResourceExhausted
471         | errno == eNOSR           = ResourceExhausted
472         | errno == eNOSTR          = InvalidArgument
473         | errno == eNOSYS          = UnsupportedOperation
474         | errno == eNOTBLK         = InvalidArgument
475         | errno == eNOTCONN        = InvalidArgument
476         | errno == eNOTDIR         = InappropriateType
477         | errno == eNOTEMPTY       = UnsatisfiedConstraints
478         | errno == eNOTSOCK        = InvalidArgument
479         | errno == eNOTTY          = IllegalOperation
480         | errno == eNXIO           = NoSuchThing
481         | errno == eOPNOTSUPP      = UnsupportedOperation
482         | errno == ePERM           = PermissionDenied
483         | errno == ePFNOSUPPORT    = UnsupportedOperation
484         | errno == ePIPE           = ResourceVanished
485         | errno == ePROCLIM        = PermissionDenied
486         | errno == ePROCUNAVAIL    = UnsupportedOperation
487         | errno == ePROGMISMATCH   = ProtocolError
488         | errno == ePROGUNAVAIL    = UnsupportedOperation
489         | errno == ePROTO          = ProtocolError
490         | errno == ePROTONOSUPPORT = ProtocolError
491         | errno == ePROTOTYPE      = ProtocolError
492         | errno == eRANGE          = UnsupportedOperation
493         | errno == eREMCHG         = ResourceVanished
494         | errno == eREMOTE         = IllegalOperation
495         | errno == eROFS           = PermissionDenied
496         | errno == eRPCMISMATCH    = ProtocolError
497         | errno == eRREMOTE        = IllegalOperation
498         | errno == eSHUTDOWN       = IllegalOperation
499         | errno == eSOCKTNOSUPPORT = UnsupportedOperation
500         | errno == eSPIPE          = UnsupportedOperation
501         | errno == eSRCH           = NoSuchThing
502         | errno == eSRMNT          = UnsatisfiedConstraints
503         | errno == eSTALE          = ResourceVanished
504         | errno == eTIME           = TimeExpired
505         | errno == eTIMEDOUT       = TimeExpired
506         | errno == eTOOMANYREFS    = ResourceExhausted
507         | errno == eTXTBSY         = ResourceBusy
508         | errno == eUSERS          = ResourceExhausted
509         | errno == eWOULDBLOCK     = OtherError
510         | errno == eXDEV           = UnsupportedOperation
511         | otherwise                = OtherError
512 #else
513     return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
514 #endif
515
516 foreign import ccall unsafe "string.h" strerror :: Errno -> IO (Ptr CChar)