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