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