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