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