1 % -----------------------------------------------------------------------------
2 % $Id: PrelCError.lhs,v 1.2 2001/01/12 17:45:30 qrczak Exp $
4 % (c) The FFI task force, 2000
7 C-specific Marshalling support: Handling of C "errno" error codes
10 {-# OPTIONS -fno-implicit-prelude #-}
12 -- this is were we get the CCONST_XXX definitions from that configure
19 -- Haskell representation for "errno" values
21 Errno(..), -- instance: Eq
22 e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
23 eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
24 eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
25 eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
26 eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
27 eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
28 eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
29 eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
30 eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,
31 eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
32 ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
33 eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
34 eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
35 eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,
37 isValidErrno, -- :: Errno -> Bool
39 -- access to the current thread's "errno" value
41 getErrno, -- :: IO Errno
42 resetErrno, -- :: IO ()
44 -- conversion of an "errno" value into IO error
46 errnoToIOError, -- :: String -- location
48 -- -> Maybe Handle -- handle
49 -- -> Maybe String -- filename
52 -- throw current "errno" value
54 throwErrno, -- :: String -> IO a
56 -- guards for IO operations that may fail
58 throwErrnoIf, -- :: (a -> Bool) -> String -> IO a -> IO a
59 throwErrnoIf_, -- :: (a -> Bool) -> String -> IO a -> IO ()
60 throwErrnoIfRetry, -- :: (a -> Bool) -> String -> IO a -> IO a
61 throwErrnoIfRetry_, -- :: (a -> Bool) -> String -> IO a -> IO ()
62 throwErrnoIfMinus1, -- :: Num a
63 -- => String -> IO a -> IO a
64 throwErrnoIfMinus1_, -- :: Num a
65 -- => String -> IO a -> IO ()
66 throwErrnoIfMinus1Retry,
68 -- => String -> IO a -> IO a
69 throwErrnoIfMinus1Retry_,
71 -- => String -> IO a -> IO ()
72 throwErrnoIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)
73 throwErrnoIfNullRetry -- :: String -> IO (Ptr a) -> IO (Ptr a)
77 -- system dependent imports
78 -- ------------------------
80 -- GHC allows us to get at the guts inside IO errors/exceptions
82 #if __GLASGOW_HASKELL__
83 #if __GLASGOW_HASKELL__ < 409
84 import PrelIOBase (IOError(..), IOErrorType(..))
86 import PrelIOBase (Exception(..), IOException(..), IOErrorType(..))
88 #endif /* __GLASGOW_HASKELL__ */
96 #if __GLASGOW_HASKELL__
98 import PrelMarshalError
107 import Ptr (Ptr, nullPtr)
109 import MarshalError (void)
111 import IO (IOError, Handle, ioError)
114 -- system dependent re-definitions
115 -- -------------------------------
117 -- we bring GHC's `IOErrorType' in scope in other compilers to simplify the
118 -- routine `errnoToIOError' below
120 #if !__GLASGOW_HASKELL__
122 = AlreadyExists | HardwareFault
123 | IllegalOperation | InappropriateType
124 | Interrupted | InvalidArgument
125 | NoSuchThing | OtherError
126 | PermissionDenied | ProtocolError
127 | ResourceBusy | ResourceExhausted
128 | ResourceVanished | SystemError
129 | TimeExpired | UnsatisfiedConstraints
130 | UnsupportedOperation
138 -- Haskell representation for "errno" values
140 newtype Errno = Errno CInt
142 instance Eq Errno where
143 errno1@(Errno no1) == errno2@(Errno no2)
144 | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
147 -- common "errno" symbols
149 e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
150 eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
151 eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
152 eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
153 eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
154 eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
155 eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
156 eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
157 eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,
158 eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
159 ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
160 eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
161 eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
162 eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV :: Errno
164 -- the CCONST_XXX identifiers are cpp symbols whose value is computed by
167 e2BIG = Errno CCONST_E2BIG
168 eACCES = Errno CCONST_EACCES
169 eADDRINUSE = Errno CCONST_EADDRINUSE
170 eADDRNOTAVAIL = Errno CCONST_EADDRNOTAVAIL
171 eADV = Errno CCONST_EADV
172 eAFNOSUPPORT = Errno CCONST_EAFNOSUPPORT
173 eAGAIN = Errno CCONST_EAGAIN
174 eALREADY = Errno CCONST_EALREADY
175 eBADF = Errno CCONST_EBADF
176 eBADMSG = Errno CCONST_EBADMSG
177 eBADRPC = Errno CCONST_EBADRPC
178 eBUSY = Errno CCONST_EBUSY
179 eCHILD = Errno CCONST_ECHILD
180 eCOMM = Errno CCONST_ECOMM
181 eCONNABORTED = Errno CCONST_ECONNABORTED
182 eCONNREFUSED = Errno CCONST_ECONNREFUSED
183 eCONNRESET = Errno CCONST_ECONNRESET
184 eDEADLK = Errno CCONST_EDEADLK
185 eDESTADDRREQ = Errno CCONST_EDESTADDRREQ
186 eDIRTY = Errno CCONST_EDIRTY
187 eDOM = Errno CCONST_EDOM
188 eDQUOT = Errno CCONST_EDQUOT
189 eEXIST = Errno CCONST_EEXIST
190 eFAULT = Errno CCONST_EFAULT
191 eFBIG = Errno CCONST_EFBIG
192 eFTYPE = Errno CCONST_EFTYPE
193 eHOSTDOWN = Errno CCONST_EHOSTDOWN
194 eHOSTUNREACH = Errno CCONST_EHOSTUNREACH
195 eIDRM = Errno CCONST_EIDRM
196 eILSEQ = Errno CCONST_EILSEQ
197 eINPROGRESS = Errno CCONST_EINPROGRESS
198 eINTR = Errno CCONST_EINTR
199 eINVAL = Errno CCONST_EINVAL
200 eIO = Errno CCONST_EIO
201 eISCONN = Errno CCONST_EISCONN
202 eISDIR = Errno CCONST_EISDIR
203 eLOOP = Errno CCONST_ELOOP
204 eMFILE = Errno CCONST_EMFILE
205 eMLINK = Errno CCONST_EMLINK
206 eMSGSIZE = Errno CCONST_EMSGSIZE
207 eMULTIHOP = Errno CCONST_EMULTIHOP
208 eNAMETOOLONG = Errno CCONST_ENAMETOOLONG
209 eNETDOWN = Errno CCONST_ENETDOWN
210 eNETRESET = Errno CCONST_ENETRESET
211 eNETUNREACH = Errno CCONST_ENETUNREACH
212 eNFILE = Errno CCONST_ENFILE
213 eNOBUFS = Errno CCONST_ENOBUFS
214 eNODATA = Errno CCONST_ENODATA
215 eNODEV = Errno CCONST_ENODEV
216 eNOENT = Errno CCONST_ENOENT
217 eNOEXEC = Errno CCONST_ENOEXEC
218 eNOLCK = Errno CCONST_ENOLCK
219 eNOLINK = Errno CCONST_ENOLINK
220 eNOMEM = Errno CCONST_ENOMEM
221 eNOMSG = Errno CCONST_ENOMSG
222 eNONET = Errno CCONST_ENONET
223 eNOPROTOOPT = Errno CCONST_ENOPROTOOPT
224 eNOSPC = Errno CCONST_ENOSPC
225 eNOSR = Errno CCONST_ENOSR
226 eNOSTR = Errno CCONST_ENOSTR
227 eNOSYS = Errno CCONST_ENOSYS
228 eNOTBLK = Errno CCONST_ENOTBLK
229 eNOTCONN = Errno CCONST_ENOTCONN
230 eNOTDIR = Errno CCONST_ENOTDIR
231 eNOTEMPTY = Errno CCONST_ENOTEMPTY
232 eNOTSOCK = Errno CCONST_ENOTSOCK
233 eNOTTY = Errno CCONST_ENOTTY
234 eNXIO = Errno CCONST_ENXIO
235 eOPNOTSUPP = Errno CCONST_EOPNOTSUPP
236 ePERM = Errno CCONST_EPERM
237 ePFNOSUPPORT = Errno CCONST_EPFNOSUPPORT
238 ePIPE = Errno CCONST_EPIPE
239 ePROCLIM = Errno CCONST_EPROCLIM
240 ePROCUNAVAIL = Errno CCONST_EPROCUNAVAIL
241 ePROGMISMATCH = Errno CCONST_EPROGMISMATCH
242 ePROGUNAVAIL = Errno CCONST_EPROGUNAVAIL
243 ePROTO = Errno CCONST_EPROTO
244 ePROTONOSUPPORT = Errno CCONST_EPROTONOSUPPORT
245 ePROTOTYPE = Errno CCONST_EPROTOTYPE
246 eRANGE = Errno CCONST_ERANGE
247 eREMCHG = Errno CCONST_EREMCHG
248 eREMOTE = Errno CCONST_EREMOTE
249 eROFS = Errno CCONST_EROFS
250 eRPCMISMATCH = Errno CCONST_ERPCMISMATCH
251 eRREMOTE = Errno CCONST_ERREMOTE
252 eSHUTDOWN = Errno CCONST_ESHUTDOWN
253 eSOCKTNOSUPPORT = Errno CCONST_ESOCKTNOSUPPORT
254 eSPIPE = Errno CCONST_ESPIPE
255 eSRCH = Errno CCONST_ESRCH
256 eSRMNT = Errno CCONST_ESRMNT
257 eSTALE = Errno CCONST_ESTALE
258 eTIME = Errno CCONST_ETIME
259 eTIMEDOUT = Errno CCONST_ETIMEDOUT
260 eTOOMANYREFS = Errno CCONST_ETOOMANYREFS
261 eTXTBSY = Errno CCONST_ETXTBSY
262 eUSERS = Errno CCONST_EUSERS
263 eWOULDBLOCK = Errno CCONST_EWOULDBLOCK
264 eXDEV = Errno CCONST_EXDEV
266 -- checks whether the given errno value is supported on the current
269 isValidErrno :: Errno -> Bool
271 -- the configure script sets all invalid "errno"s to 0
273 isValidErrno (Errno errno) = errno /= 0
276 -- access to the current thread's "errno" value
277 -- --------------------------------------------
279 -- yield the current thread's "errno" value
282 getErrno = liftM Errno (peek _errno)
285 -- set the current thread's "errno" value to 0
288 resetErrno = poke _errno 0
291 -- throw current "errno" value
292 -- ---------------------------
294 -- the common case: throw an IO error based on a textual description
295 -- of the error location and the current thread's "errno" value
297 throwErrno :: String -> IO a
301 ioError (errnoToIOError loc errno Nothing Nothing)
304 -- guards for IO operations that may fail
305 -- --------------------------------------
307 -- guard an IO operation and throw an "errno" based exception of the result
308 -- value of the IO operation meets the given predicate
310 throwErrnoIf :: (a -> Bool) -> String -> IO a -> IO a
311 throwErrnoIf pred loc f =
314 if pred res then throwErrno loc else return res
316 -- as `throwErrnoIf', but discards the result
318 throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO ()
319 throwErrnoIf_ pred loc f = void $ throwErrnoIf pred loc f
321 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
324 throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a
325 throwErrnoIfRetry pred loc f =
332 then throwErrnoIfRetry pred loc f
336 -- as `throwErrnoIfRetry', but discards the result
338 throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO ()
339 throwErrnoIfRetry_ pred loc f = void $ throwErrnoIfRetry pred loc f
341 -- throws "errno" if a result of "-1" is returned
343 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
344 throwErrnoIfMinus1 = throwErrnoIf (== -1)
346 -- as `throwErrnoIfMinus1', but discards the result
348 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
349 throwErrnoIfMinus1_ = throwErrnoIf_ (== -1)
351 -- throws "errno" if a result of "-1" is returned, but retries in case of an
352 -- interrupted operation
354 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
355 throwErrnoIfMinus1Retry = throwErrnoIfRetry (== -1)
357 -- as `throwErrnoIfMinus1', but discards the result
359 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
360 throwErrnoIfMinus1Retry_ = throwErrnoIfRetry_ (== -1)
362 -- throws "errno" if a result of a NULL pointer is returned
364 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
365 throwErrnoIfNull = throwErrnoIf (== nullPtr)
367 -- throws "errno" if a result of a NULL pointer is returned, but retries in
368 -- case of an interrupted operation
370 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
371 throwErrnoIfNullRetry = throwErrnoIfRetry (== nullPtr)
374 -- conversion of an "errno" value into IO error
375 -- --------------------------------------------
377 -- convert a location string, an "errno" value, an optional handle,
378 -- and an optional filename into a matching IO error
380 errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
381 errnoToIOError loc errno@(Errno no) maybeHdl maybeName =
382 #if __GLASGOW_HASKELL__
383 IOException (IOError maybeHdl errType loc str maybeName)
385 userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName)
389 | no == 0 = (OtherError,
391 | errno == e2BIG = (ResourceExhausted,
392 "argument list too long")
393 | errno == eACCES = (PermissionDenied,
394 "inadequate access permission")
395 | errno == eADDRINUSE = (ResourceBusy,
396 "address already in use")
397 | errno == eADDRNOTAVAIL = (UnsupportedOperation,
398 "address not available")
399 | errno == eADV = (OtherError,
400 "RFS advertise error")
401 | errno == eAFNOSUPPORT = (UnsupportedOperation,
402 "address family not supported by " ++
404 -- no multiline strings with cpp
405 | errno == eAGAIN = (ResourceExhausted,
406 "insufficient resources")
407 | errno == eALREADY = (AlreadyExists,
408 "operation already in progress")
409 | errno == eBADF = (OtherError,
410 "internal error (EBADF)")
411 | errno == eBADMSG = (InappropriateType,
412 "next message has wrong type")
413 | errno == eBADRPC = (OtherError,
414 "invalid RPC request or response")
415 | errno == eBUSY = (ResourceBusy,
417 | errno == eCHILD = (NoSuchThing,
418 "no child processes")
419 | errno == eCOMM = (ResourceVanished,
420 "no virtual circuit could be found")
421 | errno == eCONNABORTED = (OtherError,
422 "aborted connection")
423 | errno == eCONNREFUSED = (NoSuchThing,
424 "no listener on remote host")
425 | errno == eCONNRESET = (ResourceVanished,
426 "connection reset by peer")
427 | errno == eDEADLK = (ResourceBusy,
428 "resource deadlock avoided")
429 | errno == eDESTADDRREQ = (InvalidArgument,
430 "destination address required")
431 | errno == eDIRTY = (UnsatisfiedConstraints,
433 | errno == eDOM = (InvalidArgument,
434 "argument too large")
435 | errno == eDQUOT = (PermissionDenied,
437 | errno == eEXIST = (AlreadyExists,
438 "file already exists")
439 | errno == eFAULT = (OtherError,
440 "internal error (EFAULT)")
441 | errno == eFBIG = (PermissionDenied,
443 | errno == eFTYPE = (InappropriateType,
444 "inappropriate NFS file type or format")
445 | errno == eHOSTDOWN = (NoSuchThing,
446 "destination host down")
447 | errno == eHOSTUNREACH = (NoSuchThing,
448 "remote host is unreachable")
449 | errno == eIDRM = (ResourceVanished,
450 "IPC identifier removed")
451 | errno == eILSEQ = (InvalidArgument,
452 "invalid wide character")
453 | errno == eINPROGRESS = (AlreadyExists,
454 "operation now in progress")
455 | errno == eINTR = (Interrupted,
456 "interrupted system call")
457 | errno == eINVAL = (InvalidArgument,
459 | errno == eIO = (HardwareFault,
461 | errno == eISCONN = (AlreadyExists,
462 "socket is already connected")
463 | errno == eISDIR = (InappropriateType,
464 "file is a directory")
465 | errno == eLOOP = (InvalidArgument,
466 "too many symbolic links")
467 | errno == eMFILE = (ResourceExhausted,
468 "process file table full")
469 | errno == eMLINK = (ResourceExhausted,
471 | errno == eMSGSIZE = (ResourceExhausted,
473 | errno == eMULTIHOP = (UnsupportedOperation,
474 "multi-hop RFS request")
475 | errno == eNAMETOOLONG = (InvalidArgument,
477 | errno == eNETDOWN = (ResourceVanished,
479 | errno == eNETRESET = (ResourceVanished,
480 "remote host rebooted; connection lost")
481 | errno == eNETUNREACH = (NoSuchThing,
482 "remote network is unreachable")
483 | errno == eNFILE = (ResourceExhausted,
484 "system file table full")
485 | errno == eNOBUFS = (ResourceExhausted,
486 "no buffer space available")
487 | errno == eNODATA = (NoSuchThing,
488 "no message on the stream head read " ++
490 -- no multiline strings with cpp
491 | errno == eNODEV = (NoSuchThing,
493 | errno == eNOENT = (NoSuchThing,
494 "no such file or directory")
495 | errno == eNOEXEC = (InvalidArgument,
496 "not an executable file")
497 | errno == eNOLCK = (ResourceExhausted,
498 "no file locks available")
499 | errno == eNOLINK = (ResourceVanished,
500 "RFS link has been severed")
501 | errno == eNOMEM = (ResourceExhausted,
502 "not enough virtual memory")
503 | errno == eNOMSG = (NoSuchThing,
504 "no message of desired type")
505 | errno == eNONET = (NoSuchThing,
506 "host is not on a network")
507 | errno == eNOPROTOOPT = (UnsupportedOperation,
508 "operation not supported by protocol")
509 | errno == eNOSPC = (ResourceExhausted,
510 "no space left on device")
511 | errno == eNOSR = (ResourceExhausted,
512 "out of stream resources")
513 | errno == eNOSTR = (InvalidArgument,
514 "not a stream device")
515 | errno == eNOSYS = (UnsupportedOperation,
516 "function not implemented")
517 | errno == eNOTBLK = (InvalidArgument,
518 "not a block device")
519 | errno == eNOTCONN = (InvalidArgument,
520 "socket is not connected")
521 | errno == eNOTDIR = (InappropriateType,
523 | errno == eNOTEMPTY = (UnsatisfiedConstraints,
524 "directory not empty")
525 | errno == eNOTSOCK = (InvalidArgument,
527 | errno == eNOTTY = (IllegalOperation,
528 "inappropriate ioctl for device")
529 | errno == eNXIO = (NoSuchThing,
530 "no such device or address")
531 | errno == eOPNOTSUPP = (UnsupportedOperation,
532 "operation not supported on socket")
533 | errno == ePERM = (PermissionDenied,
534 "privileged operation")
535 | errno == ePFNOSUPPORT = (UnsupportedOperation,
536 "protocol family not supported")
537 | errno == ePIPE = (ResourceVanished,
539 | errno == ePROCLIM = (PermissionDenied,
540 "too many processes")
541 | errno == ePROCUNAVAIL = (UnsupportedOperation,
542 "unimplemented RPC procedure")
543 | errno == ePROGMISMATCH = (ProtocolError,
544 "unsupported RPC program version")
545 | errno == ePROGUNAVAIL = (UnsupportedOperation,
546 "RPC program unavailable")
547 | errno == ePROTO = (ProtocolError,
548 "error in streams protocol")
549 | errno == ePROTONOSUPPORT = (ProtocolError,
550 "protocol not supported")
551 | errno == ePROTOTYPE = (ProtocolError,
552 "wrong protocol for socket")
553 | errno == eRANGE = (UnsupportedOperation,
555 | errno == eREMCHG = (ResourceVanished,
556 "remote address changed")
557 | errno == eREMOTE = (IllegalOperation,
558 "too many levels of remote in path")
559 | errno == eROFS = (PermissionDenied,
560 "read-only file system")
561 | errno == eRPCMISMATCH = (ProtocolError,
562 "RPC version is wrong")
563 | errno == eRREMOTE = (IllegalOperation,
565 | errno == eSHUTDOWN = (IllegalOperation,
566 "can't send after socket shutdown")
567 | errno == eSOCKTNOSUPPORT = (UnsupportedOperation,
568 "socket type not supported")
569 | errno == eSPIPE = (UnsupportedOperation,
570 "can't seek on a pipe")
571 | errno == eSRCH = (NoSuchThing,
573 | errno == eSRMNT = (UnsatisfiedConstraints,
574 "RFS resources still mounted by " ++
576 -- no multiline strings with cpp
577 | errno == eSTALE = (ResourceVanished,
578 "stale NFS file handle")
579 | errno == eTIME = (TimeExpired,
581 | errno == eTIMEDOUT = (TimeExpired,
582 "connection timed out")
583 | errno == eTOOMANYREFS = (ResourceExhausted,
584 "too many references; can't splice")
585 | errno == eTXTBSY = (ResourceBusy,
587 | errno == eUSERS = (ResourceExhausted,
589 | errno == eWOULDBLOCK = (OtherError,
590 "operation would block")
591 | errno == eXDEV = (UnsupportedOperation,
592 "can't make a cross-device link")
593 | otherwise = (OtherError,
594 "unexpected error (error code: "
597 foreign label "errno" _errno :: Ptr CInt
598 -- FIXME: this routine should eventually be provided by the Haskell runtime
599 -- and guarantee that the "errno" of the last operation performed by
600 -- the current thread is returned