1 {-# OPTIONS -fno-implicit-prelude -#include "HsBase.h" #-}
2 -----------------------------------------------------------------------------
4 -- Module : Foreign.C.Error
5 -- Copyright : (c) The FFI task force 2001
6 -- License : BSD-style (see the file libraries/base/LICENSE)
8 -- Maintainer : ffi@haskell.org
9 -- Stability : provisional
10 -- Portability : portable
12 -- C-specific Marshalling support: Handling of C \"errno\" error codes
14 -----------------------------------------------------------------------------
16 module Foreign.C.Error (
18 -- Haskell representation for "errno" values
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,
36 isValidErrno, -- :: Errno -> Bool
38 -- access to the current thread's "errno" value
40 getErrno, -- :: IO Errno
41 resetErrno, -- :: IO ()
43 -- conversion of an "errno" value into IO error
45 errnoToIOError, -- :: String -- location
47 -- -> Maybe Handle -- handle
48 -- -> Maybe String -- filename
51 -- throw current "errno" value
53 throwErrno, -- :: String -> IO a
55 -- guards for IO operations that may fail
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,
67 -- => String -> IO a -> IO a
68 throwErrnoIfMinus1Retry_,
70 -- => String -> IO a -> IO ()
71 throwErrnoIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)
72 throwErrnoIfNullRetry,-- :: String -> IO (Ptr a) -> IO (Ptr a)
74 throwErrnoIfRetryMayBlock,
75 throwErrnoIfRetryMayBlock_,
76 throwErrnoIfMinus1RetryMayBlock,
77 throwErrnoIfMinus1RetryMayBlock_,
78 throwErrnoIfNullRetryMayBlock
82 -- this is were we get the CCONST_XXX definitions from that configure
89 -- system dependent imports
90 -- ------------------------
92 -- GHC allows us to get at the guts inside IO errors/exceptions
94 #if __GLASGOW_HASKELL__
95 import GHC.IOBase (IOException(..), IOErrorType(..))
96 #endif /* __GLASGOW_HASKELL__ */
102 import Foreign.Storable
104 import Foreign.C.Types
105 import Foreign.C.String
106 import Foreign.Marshal.Error ( void )
109 #if __GLASGOW_HASKELL__
115 import System.IO ( IOError, Handle, ioError )
116 import System.IO.Unsafe ( unsafePerformIO )
120 {-# CBITS errno.c #-}
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]
132 foreign import ccall unsafe "errno.h &errno" _errno :: Ptr CInt
134 foreign import ccall unsafe "HsBase.h ghcErrno" _errno :: Ptr CInt
137 -- Haskell representation for "errno" values
139 newtype Errno = Errno CInt
141 instance Eq Errno where
142 errno1@(Errno no1) == errno2@(Errno no2)
143 | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
146 -- common "errno" symbols
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
163 -- the cCONST_XXX identifiers are cpp symbols whose value is computed by
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)
270 -- checks whether the given errno value is supported on the current
273 isValidErrno :: Errno -> Bool
275 -- the configure script sets all invalid "errno"s to -1
277 isValidErrno (Errno errno) = errno /= -1
280 -- access to the current thread's "errno" value
281 -- --------------------------------------------
283 -- yield the current thread's "errno" value
286 getErrno = do e <- peek _errno; return (Errno e)
288 -- set the current thread's "errno" value to 0
291 resetErrno = poke _errno 0
294 -- throw current "errno" value
295 -- ---------------------------
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
300 throwErrno :: String -> IO a
304 ioError (errnoToIOError loc errno Nothing Nothing)
307 -- guards for IO operations that may fail
308 -- --------------------------------------
310 -- guard an IO operation and throw an "errno" based exception of the result
311 -- value of the IO operation meets the given predicate
313 throwErrnoIf :: (a -> Bool) -> String -> IO a -> IO a
314 throwErrnoIf pred loc f =
317 if pred res then throwErrno loc else return res
319 -- as `throwErrnoIf', but discards the result
321 throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO ()
322 throwErrnoIf_ pred loc f = void $ throwErrnoIf pred loc f
324 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
327 throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a
328 throwErrnoIfRetry pred loc f =
335 then throwErrnoIfRetry pred loc f
339 -- as `throwErrnoIfRetry', but checks for operations that would block and
340 -- executes an alternative action in that case.
342 throwErrnoIfRetryMayBlock :: (a -> Bool) -> String -> IO a -> IO b -> IO a
343 throwErrnoIfRetryMayBlock pred loc f on_block =
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
356 -- as `throwErrnoIfRetry', but discards the result
358 throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO ()
359 throwErrnoIfRetry_ pred loc f = void $ throwErrnoIfRetry pred loc f
361 -- as `throwErrnoIfRetryMayBlock', but discards the result
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
367 -- throws "errno" if a result of "-1" is returned
369 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
370 throwErrnoIfMinus1 = throwErrnoIf (== -1)
372 -- as `throwErrnoIfMinus1', but discards the result
374 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
375 throwErrnoIfMinus1_ = throwErrnoIf_ (== -1)
377 -- throws "errno" if a result of "-1" is returned, but retries in case of an
378 -- interrupted operation
380 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
381 throwErrnoIfMinus1Retry = throwErrnoIfRetry (== -1)
383 -- as `throwErrnoIfMinus1', but discards the result
385 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
386 throwErrnoIfMinus1Retry_ = throwErrnoIfRetry_ (== -1)
388 -- as throwErrnoIfMinus1Retry, but checks for operations that would block
390 throwErrnoIfMinus1RetryMayBlock :: Num a => String -> IO a -> IO b -> IO a
391 throwErrnoIfMinus1RetryMayBlock = throwErrnoIfRetryMayBlock (== -1)
393 -- as `throwErrnoIfMinus1RetryMayBlock', but discards the result
395 throwErrnoIfMinus1RetryMayBlock_ :: Num a => String -> IO a -> IO b -> IO ()
396 throwErrnoIfMinus1RetryMayBlock_ = throwErrnoIfRetryMayBlock_ (== -1)
398 -- throws "errno" if a result of a NULL pointer is returned
400 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
401 throwErrnoIfNull = throwErrnoIf (== nullPtr)
403 -- throws "errno" if a result of a NULL pointer is returned, but retries in
404 -- case of an interrupted operation
406 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
407 throwErrnoIfNullRetry = throwErrnoIfRetry (== nullPtr)
409 -- as throwErrnoIfNullRetry, but checks for operations that would block
411 throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)
412 throwErrnoIfNullRetryMayBlock = throwErrnoIfRetryMayBlock (== nullPtr)
414 -- conversion of an "errno" value into IO error
415 -- --------------------------------------------
417 -- convert a location string, an "errno" value, an optional handle,
418 -- and an optional filename into a matching IO error
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)
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
528 return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
531 foreign import ccall unsafe "string.h" strerror :: Errno -> IO (Ptr CChar)