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