[project @ 2004-01-06 12:40:00 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 CONST_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.IOBase
111 import GHC.Num
112 import GHC.Base
113 #else
114 import System.IO                ( IOError, Handle, ioError )
115 import System.IO.Unsafe         ( unsafePerformIO )
116 #endif
117
118 #ifdef __HUGS__
119 {-# CBITS errno.c #-}
120 #endif
121
122
123 -- "errno" type
124 -- ------------
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 #ifdef __NHC__
157 #include "Errno.hs"
158 #else
159 e2BIG           = Errno (CONST_E2BIG)
160 eACCES          = Errno (CONST_EACCES)
161 eADDRINUSE      = Errno (CONST_EADDRINUSE)
162 eADDRNOTAVAIL   = Errno (CONST_EADDRNOTAVAIL)
163 eADV            = Errno (CONST_EADV)
164 eAFNOSUPPORT    = Errno (CONST_EAFNOSUPPORT)
165 eAGAIN          = Errno (CONST_EAGAIN)
166 eALREADY        = Errno (CONST_EALREADY)
167 eBADF           = Errno (CONST_EBADF)
168 eBADMSG         = Errno (CONST_EBADMSG)
169 eBADRPC         = Errno (CONST_EBADRPC)
170 eBUSY           = Errno (CONST_EBUSY)
171 eCHILD          = Errno (CONST_ECHILD)
172 eCOMM           = Errno (CONST_ECOMM)
173 eCONNABORTED    = Errno (CONST_ECONNABORTED)
174 eCONNREFUSED    = Errno (CONST_ECONNREFUSED)
175 eCONNRESET      = Errno (CONST_ECONNRESET)
176 eDEADLK         = Errno (CONST_EDEADLK)
177 eDESTADDRREQ    = Errno (CONST_EDESTADDRREQ)
178 eDIRTY          = Errno (CONST_EDIRTY)
179 eDOM            = Errno (CONST_EDOM)
180 eDQUOT          = Errno (CONST_EDQUOT)
181 eEXIST          = Errno (CONST_EEXIST)
182 eFAULT          = Errno (CONST_EFAULT)
183 eFBIG           = Errno (CONST_EFBIG)
184 eFTYPE          = Errno (CONST_EFTYPE)
185 eHOSTDOWN       = Errno (CONST_EHOSTDOWN)
186 eHOSTUNREACH    = Errno (CONST_EHOSTUNREACH)
187 eIDRM           = Errno (CONST_EIDRM)
188 eILSEQ          = Errno (CONST_EILSEQ)
189 eINPROGRESS     = Errno (CONST_EINPROGRESS)
190 eINTR           = Errno (CONST_EINTR)
191 eINVAL          = Errno (CONST_EINVAL)
192 eIO             = Errno (CONST_EIO)
193 eISCONN         = Errno (CONST_EISCONN)
194 eISDIR          = Errno (CONST_EISDIR)
195 eLOOP           = Errno (CONST_ELOOP)
196 eMFILE          = Errno (CONST_EMFILE)
197 eMLINK          = Errno (CONST_EMLINK)
198 eMSGSIZE        = Errno (CONST_EMSGSIZE)
199 eMULTIHOP       = Errno (CONST_EMULTIHOP)
200 eNAMETOOLONG    = Errno (CONST_ENAMETOOLONG)
201 eNETDOWN        = Errno (CONST_ENETDOWN)
202 eNETRESET       = Errno (CONST_ENETRESET)
203 eNETUNREACH     = Errno (CONST_ENETUNREACH)
204 eNFILE          = Errno (CONST_ENFILE)
205 eNOBUFS         = Errno (CONST_ENOBUFS)
206 eNODATA         = Errno (CONST_ENODATA)
207 eNODEV          = Errno (CONST_ENODEV)
208 eNOENT          = Errno (CONST_ENOENT)
209 eNOEXEC         = Errno (CONST_ENOEXEC)
210 eNOLCK          = Errno (CONST_ENOLCK)
211 eNOLINK         = Errno (CONST_ENOLINK)
212 eNOMEM          = Errno (CONST_ENOMEM)
213 eNOMSG          = Errno (CONST_ENOMSG)
214 eNONET          = Errno (CONST_ENONET)
215 eNOPROTOOPT     = Errno (CONST_ENOPROTOOPT)
216 eNOSPC          = Errno (CONST_ENOSPC)
217 eNOSR           = Errno (CONST_ENOSR)
218 eNOSTR          = Errno (CONST_ENOSTR)
219 eNOSYS          = Errno (CONST_ENOSYS)
220 eNOTBLK         = Errno (CONST_ENOTBLK)
221 eNOTCONN        = Errno (CONST_ENOTCONN)
222 eNOTDIR         = Errno (CONST_ENOTDIR)
223 eNOTEMPTY       = Errno (CONST_ENOTEMPTY)
224 eNOTSOCK        = Errno (CONST_ENOTSOCK)
225 eNOTTY          = Errno (CONST_ENOTTY)
226 eNXIO           = Errno (CONST_ENXIO)
227 eOPNOTSUPP      = Errno (CONST_EOPNOTSUPP)
228 ePERM           = Errno (CONST_EPERM)
229 ePFNOSUPPORT    = Errno (CONST_EPFNOSUPPORT)
230 ePIPE           = Errno (CONST_EPIPE)
231 ePROCLIM        = Errno (CONST_EPROCLIM)
232 ePROCUNAVAIL    = Errno (CONST_EPROCUNAVAIL)
233 ePROGMISMATCH   = Errno (CONST_EPROGMISMATCH)
234 ePROGUNAVAIL    = Errno (CONST_EPROGUNAVAIL)
235 ePROTO          = Errno (CONST_EPROTO)
236 ePROTONOSUPPORT = Errno (CONST_EPROTONOSUPPORT)
237 ePROTOTYPE      = Errno (CONST_EPROTOTYPE)
238 eRANGE          = Errno (CONST_ERANGE)
239 eREMCHG         = Errno (CONST_EREMCHG)
240 eREMOTE         = Errno (CONST_EREMOTE)
241 eROFS           = Errno (CONST_EROFS)
242 eRPCMISMATCH    = Errno (CONST_ERPCMISMATCH)
243 eRREMOTE        = Errno (CONST_ERREMOTE)
244 eSHUTDOWN       = Errno (CONST_ESHUTDOWN)
245 eSOCKTNOSUPPORT = Errno (CONST_ESOCKTNOSUPPORT)
246 eSPIPE          = Errno (CONST_ESPIPE)
247 eSRCH           = Errno (CONST_ESRCH)
248 eSRMNT          = Errno (CONST_ESRMNT)
249 eSTALE          = Errno (CONST_ESTALE)
250 eTIME           = Errno (CONST_ETIME)
251 eTIMEDOUT       = Errno (CONST_ETIMEDOUT)
252 eTOOMANYREFS    = Errno (CONST_ETOOMANYREFS)
253 eTXTBSY         = Errno (CONST_ETXTBSY)
254 eUSERS          = Errno (CONST_EUSERS)
255 eWOULDBLOCK     = Errno (CONST_EWOULDBLOCK)
256 eXDEV           = Errno (CONST_EXDEV)
257 #endif
258
259 -- checks whether the given errno value is supported on the current
260 -- architecture
261 --
262 isValidErrno               :: Errno -> Bool
263 --
264 -- the configure script sets all invalid "errno"s to -1
265 --
266 isValidErrno (Errno errno)  = errno /= -1
267
268
269 -- access to the current thread's "errno" value
270 -- --------------------------------------------
271
272 -- yield the current thread's "errno" value
273 --
274 getErrno :: IO Errno
275
276 -- We must call a C function to get the value of errno in general.  On
277 -- threaded systems, errno is hidden behind a C macro so that each OS
278 -- thread gets its own copy.
279 #ifdef __NHC__
280 getErrno = do e <- peek _errno; return (Errno e)
281 foreign import ccall unsafe "errno.h &errno" _errno :: IO (Ptr CInt)
282 #else
283 getErrno = do e <- get_errno; return (Errno e)
284 foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO CInt
285 #endif
286
287 -- set the current thread's "errno" value to 0
288 --
289 resetErrno :: IO ()
290
291 -- Again, setting errno has to be done via a C function.
292 #ifdef __NHC__
293 resetErrno = poke _errno 0
294 #else
295 resetErrno = set_errno 0
296 foreign import ccall unsafe "HsBase.h __hscore_set_errno" set_errno :: CInt -> IO ()
297 #endif
298
299 -- throw current "errno" value
300 -- ---------------------------
301
302 -- the common case: throw an IO error based on a textual description
303 -- of the error location and the current thread's "errno" value
304 --
305 throwErrno     :: String -> IO a
306 throwErrno loc  =
307   do
308     errno <- getErrno
309     ioError (errnoToIOError loc errno Nothing Nothing)
310
311
312 -- guards for IO operations that may fail
313 -- --------------------------------------
314
315 -- guard an IO operation and throw an "errno" based exception of the result
316 -- value of the IO operation meets the given predicate
317 --
318 throwErrnoIf            :: (a -> Bool) -> String -> IO a -> IO a
319 throwErrnoIf pred loc f  = 
320   do
321     res <- f
322     if pred res then throwErrno loc else return res
323
324 -- as `throwErrnoIf', but discards the result
325 --
326 throwErrnoIf_            :: (a -> Bool) -> String -> IO a -> IO ()
327 throwErrnoIf_ pred loc f  = void $ throwErrnoIf pred loc f
328
329 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
330 -- flag `EINTR')
331 --
332 throwErrnoIfRetry            :: (a -> Bool) -> String -> IO a -> IO a
333 throwErrnoIfRetry pred loc f  = 
334   do
335     res <- f
336     if pred res
337       then do
338         err <- getErrno
339         if err == eINTR
340           then throwErrnoIfRetry pred loc f
341           else throwErrno loc
342       else return res
343
344 -- as `throwErrnoIfRetry', but checks for operations that would block and
345 -- executes an alternative action in that case.
346
347 throwErrnoIfRetryMayBlock  :: (a -> Bool) -> String -> IO a -> IO b -> IO a
348 throwErrnoIfRetryMayBlock pred loc f on_block  = 
349   do
350     res <- f
351     if pred res
352       then do
353         err <- getErrno
354         if err == eINTR
355           then throwErrnoIfRetryMayBlock pred loc f on_block
356           else if err == eWOULDBLOCK || err == eAGAIN
357                  then do on_block; throwErrnoIfRetryMayBlock pred loc f on_block
358                  else throwErrno loc
359       else return res
360
361 -- as `throwErrnoIfRetry', but discards the result
362 --
363 throwErrnoIfRetry_            :: (a -> Bool) -> String -> IO a -> IO ()
364 throwErrnoIfRetry_ pred loc f  = void $ throwErrnoIfRetry pred loc f
365
366 -- as `throwErrnoIfRetryMayBlock', but discards the result
367 --
368 throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO ()
369 throwErrnoIfRetryMayBlock_ pred loc f on_block 
370   = void $ throwErrnoIfRetryMayBlock pred loc f on_block
371
372 -- throws "errno" if a result of "-1" is returned
373 --
374 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
375 throwErrnoIfMinus1  = throwErrnoIf (== -1)
376
377 -- as `throwErrnoIfMinus1', but discards the result
378 --
379 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
380 throwErrnoIfMinus1_  = throwErrnoIf_ (== -1)
381
382 -- throws "errno" if a result of "-1" is returned, but retries in case of an
383 -- interrupted operation
384 --
385 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
386 throwErrnoIfMinus1Retry  = throwErrnoIfRetry (== -1)
387
388 -- as `throwErrnoIfMinus1', but discards the result
389 --
390 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
391 throwErrnoIfMinus1Retry_  = throwErrnoIfRetry_ (== -1)
392
393 -- as throwErrnoIfMinus1Retry, but checks for operations that would block
394 --
395 throwErrnoIfMinus1RetryMayBlock :: Num a => String -> IO a -> IO b -> IO a
396 throwErrnoIfMinus1RetryMayBlock  = throwErrnoIfRetryMayBlock (== -1)
397
398 -- as `throwErrnoIfMinus1RetryMayBlock', but discards the result
399 --
400 throwErrnoIfMinus1RetryMayBlock_ :: Num a => String -> IO a -> IO b -> IO ()
401 throwErrnoIfMinus1RetryMayBlock_  = throwErrnoIfRetryMayBlock_ (== -1)
402
403 -- throws "errno" if a result of a NULL pointer is returned
404 --
405 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
406 throwErrnoIfNull  = throwErrnoIf (== nullPtr)
407
408 -- throws "errno" if a result of a NULL pointer is returned, but retries in
409 -- case of an interrupted operation
410 --
411 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
412 throwErrnoIfNullRetry  = throwErrnoIfRetry (== nullPtr)
413
414 -- as throwErrnoIfNullRetry, but checks for operations that would block
415 --
416 throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)
417 throwErrnoIfNullRetryMayBlock  = throwErrnoIfRetryMayBlock (== nullPtr)
418
419 -- conversion of an "errno" value into IO error
420 -- --------------------------------------------
421
422 -- convert a location string, an "errno" value, an optional handle,
423 -- and an optional filename into a matching IO error
424 --
425 errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
426 errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do
427     str <- strerror errno >>= peekCString
428 #if __GLASGOW_HASKELL__
429     return (IOError maybeHdl errType loc str maybeName)
430     where
431     errType
432         | errno == eOK             = OtherError
433         | errno == e2BIG           = ResourceExhausted
434         | errno == eACCES          = PermissionDenied
435         | errno == eADDRINUSE      = ResourceBusy
436         | errno == eADDRNOTAVAIL   = UnsupportedOperation
437         | errno == eADV            = OtherError
438         | errno == eAFNOSUPPORT    = UnsupportedOperation
439         | errno == eAGAIN          = ResourceExhausted
440         | errno == eALREADY        = AlreadyExists
441         | errno == eBADF           = OtherError
442         | errno == eBADMSG         = InappropriateType
443         | errno == eBADRPC         = OtherError
444         | errno == eBUSY           = ResourceBusy
445         | errno == eCHILD          = NoSuchThing
446         | errno == eCOMM           = ResourceVanished
447         | errno == eCONNABORTED    = OtherError
448         | errno == eCONNREFUSED    = NoSuchThing
449         | errno == eCONNRESET      = ResourceVanished
450         | errno == eDEADLK         = ResourceBusy
451         | errno == eDESTADDRREQ    = InvalidArgument
452         | errno == eDIRTY          = UnsatisfiedConstraints
453         | errno == eDOM            = InvalidArgument
454         | errno == eDQUOT          = PermissionDenied
455         | errno == eEXIST          = AlreadyExists
456         | errno == eFAULT          = OtherError
457         | errno == eFBIG           = PermissionDenied
458         | errno == eFTYPE          = InappropriateType
459         | errno == eHOSTDOWN       = NoSuchThing
460         | errno == eHOSTUNREACH    = NoSuchThing
461         | errno == eIDRM           = ResourceVanished
462         | errno == eILSEQ          = InvalidArgument
463         | errno == eINPROGRESS     = AlreadyExists
464         | errno == eINTR           = Interrupted
465         | errno == eINVAL          = InvalidArgument
466         | errno == eIO             = HardwareFault
467         | errno == eISCONN         = AlreadyExists
468         | errno == eISDIR          = InappropriateType
469         | errno == eLOOP           = InvalidArgument
470         | errno == eMFILE          = ResourceExhausted
471         | errno == eMLINK          = ResourceExhausted
472         | errno == eMSGSIZE        = ResourceExhausted
473         | errno == eMULTIHOP       = UnsupportedOperation
474         | errno == eNAMETOOLONG    = InvalidArgument
475         | errno == eNETDOWN        = ResourceVanished
476         | errno == eNETRESET       = ResourceVanished
477         | errno == eNETUNREACH     = NoSuchThing
478         | errno == eNFILE          = ResourceExhausted
479         | errno == eNOBUFS         = ResourceExhausted
480         | errno == eNODATA         = NoSuchThing
481         | errno == eNODEV          = UnsupportedOperation
482         | errno == eNOENT          = NoSuchThing
483         | errno == eNOEXEC         = InvalidArgument
484         | errno == eNOLCK          = ResourceExhausted
485         | errno == eNOLINK         = ResourceVanished
486         | errno == eNOMEM          = ResourceExhausted
487         | errno == eNOMSG          = NoSuchThing
488         | errno == eNONET          = NoSuchThing
489         | errno == eNOPROTOOPT     = UnsupportedOperation
490         | errno == eNOSPC          = ResourceExhausted
491         | errno == eNOSR           = ResourceExhausted
492         | errno == eNOSTR          = InvalidArgument
493         | errno == eNOSYS          = UnsupportedOperation
494         | errno == eNOTBLK         = InvalidArgument
495         | errno == eNOTCONN        = InvalidArgument
496         | errno == eNOTDIR         = InappropriateType
497         | errno == eNOTEMPTY       = UnsatisfiedConstraints
498         | errno == eNOTSOCK        = InvalidArgument
499         | errno == eNOTTY          = IllegalOperation
500         | errno == eNXIO           = NoSuchThing
501         | errno == eOPNOTSUPP      = UnsupportedOperation
502         | errno == ePERM           = PermissionDenied
503         | errno == ePFNOSUPPORT    = UnsupportedOperation
504         | errno == ePIPE           = ResourceVanished
505         | errno == ePROCLIM        = PermissionDenied
506         | errno == ePROCUNAVAIL    = UnsupportedOperation
507         | errno == ePROGMISMATCH   = ProtocolError
508         | errno == ePROGUNAVAIL    = UnsupportedOperation
509         | errno == ePROTO          = ProtocolError
510         | errno == ePROTONOSUPPORT = ProtocolError
511         | errno == ePROTOTYPE      = ProtocolError
512         | errno == eRANGE          = UnsupportedOperation
513         | errno == eREMCHG         = ResourceVanished
514         | errno == eREMOTE         = IllegalOperation
515         | errno == eROFS           = PermissionDenied
516         | errno == eRPCMISMATCH    = ProtocolError
517         | errno == eRREMOTE        = IllegalOperation
518         | errno == eSHUTDOWN       = IllegalOperation
519         | errno == eSOCKTNOSUPPORT = UnsupportedOperation
520         | errno == eSPIPE          = UnsupportedOperation
521         | errno == eSRCH           = NoSuchThing
522         | errno == eSRMNT          = UnsatisfiedConstraints
523         | errno == eSTALE          = ResourceVanished
524         | errno == eTIME           = TimeExpired
525         | errno == eTIMEDOUT       = TimeExpired
526         | errno == eTOOMANYREFS    = ResourceExhausted
527         | errno == eTXTBSY         = ResourceBusy
528         | errno == eUSERS          = ResourceExhausted
529         | errno == eWOULDBLOCK     = OtherError
530         | errno == eXDEV           = UnsupportedOperation
531         | otherwise                = OtherError
532 #else
533     return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
534 #endif
535
536 foreign import ccall unsafe "string.h" strerror :: Errno -> IO (Ptr CChar)