1 % -----------------------------------------------------------------------------
2 % $Id: PrelCError.lhs,v 1.7 2001/03/16 21:47:41 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 -#include "cbits/ghc_errno.h" #-}
12 -- this is were we get the CCONST_XXX definitions from that configure
19 -- Haskell representation for "errno" values
21 Errno(..), -- instance: Eq
22 eOK, 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
108 import Ptr (Ptr, nullPtr)
110 import CString (peekCString)
111 import MarshalError (void)
113 import IO (IOError, Handle, ioError)
119 -- import of C function that gives address of errno
121 foreign import "ghcErrno" unsafe _errno :: Ptr CInt
123 -- Haskell representation for "errno" values
125 newtype Errno = Errno CInt
127 instance Eq Errno where
128 errno1@(Errno no1) == errno2@(Errno no2)
129 | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
132 -- common "errno" symbols
134 eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
135 eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
136 eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
137 eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
138 eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
139 eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
140 eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
141 eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
142 eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,
143 eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
144 ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
145 eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
146 eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
147 eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV :: Errno
149 -- the CCONST_XXX identifiers are cpp symbols whose value is computed by
153 e2BIG = Errno (CCONST_E2BIG)
154 eACCES = Errno (CCONST_EACCES)
155 eADDRINUSE = Errno (CCONST_EADDRINUSE)
156 eADDRNOTAVAIL = Errno (CCONST_EADDRNOTAVAIL)
157 eADV = Errno (CCONST_EADV)
158 eAFNOSUPPORT = Errno (CCONST_EAFNOSUPPORT)
159 eAGAIN = Errno (CCONST_EAGAIN)
160 eALREADY = Errno (CCONST_EALREADY)
161 eBADF = Errno (CCONST_EBADF)
162 eBADMSG = Errno (CCONST_EBADMSG)
163 eBADRPC = Errno (CCONST_EBADRPC)
164 eBUSY = Errno (CCONST_EBUSY)
165 eCHILD = Errno (CCONST_ECHILD)
166 eCOMM = Errno (CCONST_ECOMM)
167 eCONNABORTED = Errno (CCONST_ECONNABORTED)
168 eCONNREFUSED = Errno (CCONST_ECONNREFUSED)
169 eCONNRESET = Errno (CCONST_ECONNRESET)
170 eDEADLK = Errno (CCONST_EDEADLK)
171 eDESTADDRREQ = Errno (CCONST_EDESTADDRREQ)
172 eDIRTY = Errno (CCONST_EDIRTY)
173 eDOM = Errno (CCONST_EDOM)
174 eDQUOT = Errno (CCONST_EDQUOT)
175 eEXIST = Errno (CCONST_EEXIST)
176 eFAULT = Errno (CCONST_EFAULT)
177 eFBIG = Errno (CCONST_EFBIG)
178 eFTYPE = Errno (CCONST_EFTYPE)
179 eHOSTDOWN = Errno (CCONST_EHOSTDOWN)
180 eHOSTUNREACH = Errno (CCONST_EHOSTUNREACH)
181 eIDRM = Errno (CCONST_EIDRM)
182 eILSEQ = Errno (CCONST_EILSEQ)
183 eINPROGRESS = Errno (CCONST_EINPROGRESS)
184 eINTR = Errno (CCONST_EINTR)
185 eINVAL = Errno (CCONST_EINVAL)
186 eIO = Errno (CCONST_EIO)
187 eISCONN = Errno (CCONST_EISCONN)
188 eISDIR = Errno (CCONST_EISDIR)
189 eLOOP = Errno (CCONST_ELOOP)
190 eMFILE = Errno (CCONST_EMFILE)
191 eMLINK = Errno (CCONST_EMLINK)
192 eMSGSIZE = Errno (CCONST_EMSGSIZE)
193 eMULTIHOP = Errno (CCONST_EMULTIHOP)
194 eNAMETOOLONG = Errno (CCONST_ENAMETOOLONG)
195 eNETDOWN = Errno (CCONST_ENETDOWN)
196 eNETRESET = Errno (CCONST_ENETRESET)
197 eNETUNREACH = Errno (CCONST_ENETUNREACH)
198 eNFILE = Errno (CCONST_ENFILE)
199 eNOBUFS = Errno (CCONST_ENOBUFS)
200 eNODATA = Errno (CCONST_ENODATA)
201 eNODEV = Errno (CCONST_ENODEV)
202 eNOENT = Errno (CCONST_ENOENT)
203 eNOEXEC = Errno (CCONST_ENOEXEC)
204 eNOLCK = Errno (CCONST_ENOLCK)
205 eNOLINK = Errno (CCONST_ENOLINK)
206 eNOMEM = Errno (CCONST_ENOMEM)
207 eNOMSG = Errno (CCONST_ENOMSG)
208 eNONET = Errno (CCONST_ENONET)
209 eNOPROTOOPT = Errno (CCONST_ENOPROTOOPT)
210 eNOSPC = Errno (CCONST_ENOSPC)
211 eNOSR = Errno (CCONST_ENOSR)
212 eNOSTR = Errno (CCONST_ENOSTR)
213 eNOSYS = Errno (CCONST_ENOSYS)
214 eNOTBLK = Errno (CCONST_ENOTBLK)
215 eNOTCONN = Errno (CCONST_ENOTCONN)
216 eNOTDIR = Errno (CCONST_ENOTDIR)
217 eNOTEMPTY = Errno (CCONST_ENOTEMPTY)
218 eNOTSOCK = Errno (CCONST_ENOTSOCK)
219 eNOTTY = Errno (CCONST_ENOTTY)
220 eNXIO = Errno (CCONST_ENXIO)
221 eOPNOTSUPP = Errno (CCONST_EOPNOTSUPP)
222 ePERM = Errno (CCONST_EPERM)
223 ePFNOSUPPORT = Errno (CCONST_EPFNOSUPPORT)
224 ePIPE = Errno (CCONST_EPIPE)
225 ePROCLIM = Errno (CCONST_EPROCLIM)
226 ePROCUNAVAIL = Errno (CCONST_EPROCUNAVAIL)
227 ePROGMISMATCH = Errno (CCONST_EPROGMISMATCH)
228 ePROGUNAVAIL = Errno (CCONST_EPROGUNAVAIL)
229 ePROTO = Errno (CCONST_EPROTO)
230 ePROTONOSUPPORT = Errno (CCONST_EPROTONOSUPPORT)
231 ePROTOTYPE = Errno (CCONST_EPROTOTYPE)
232 eRANGE = Errno (CCONST_ERANGE)
233 eREMCHG = Errno (CCONST_EREMCHG)
234 eREMOTE = Errno (CCONST_EREMOTE)
235 eROFS = Errno (CCONST_EROFS)
236 eRPCMISMATCH = Errno (CCONST_ERPCMISMATCH)
237 eRREMOTE = Errno (CCONST_ERREMOTE)
238 eSHUTDOWN = Errno (CCONST_ESHUTDOWN)
239 eSOCKTNOSUPPORT = Errno (CCONST_ESOCKTNOSUPPORT)
240 eSPIPE = Errno (CCONST_ESPIPE)
241 eSRCH = Errno (CCONST_ESRCH)
242 eSRMNT = Errno (CCONST_ESRMNT)
243 eSTALE = Errno (CCONST_ESTALE)
244 eTIME = Errno (CCONST_ETIME)
245 eTIMEDOUT = Errno (CCONST_ETIMEDOUT)
246 eTOOMANYREFS = Errno (CCONST_ETOOMANYREFS)
247 eTXTBSY = Errno (CCONST_ETXTBSY)
248 eUSERS = Errno (CCONST_EUSERS)
249 eWOULDBLOCK = Errno (CCONST_EWOULDBLOCK)
250 eXDEV = Errno (CCONST_EXDEV)
252 -- checks whether the given errno value is supported on the current
255 isValidErrno :: Errno -> Bool
257 -- the configure script sets all invalid "errno"s to -1
259 isValidErrno (Errno errno) = errno /= -1
262 -- access to the current thread's "errno" value
263 -- --------------------------------------------
265 -- yield the current thread's "errno" value
268 getErrno = liftM Errno (peek _errno)
271 -- set the current thread's "errno" value to 0
274 resetErrno = poke _errno 0
277 -- throw current "errno" value
278 -- ---------------------------
280 -- the common case: throw an IO error based on a textual description
281 -- of the error location and the current thread's "errno" value
283 throwErrno :: String -> IO a
287 ioError (errnoToIOError loc errno Nothing Nothing)
290 -- guards for IO operations that may fail
291 -- --------------------------------------
293 -- guard an IO operation and throw an "errno" based exception of the result
294 -- value of the IO operation meets the given predicate
296 throwErrnoIf :: (a -> Bool) -> String -> IO a -> IO a
297 throwErrnoIf pred loc f =
300 if pred res then throwErrno loc else return res
302 -- as `throwErrnoIf', but discards the result
304 throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO ()
305 throwErrnoIf_ pred loc f = void $ throwErrnoIf pred loc f
307 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
310 throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a
311 throwErrnoIfRetry pred loc f =
318 then throwErrnoIfRetry pred loc f
322 -- as `throwErrnoIfRetry', but discards the result
324 throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO ()
325 throwErrnoIfRetry_ pred loc f = void $ throwErrnoIfRetry pred loc f
327 -- throws "errno" if a result of "-1" is returned
329 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
330 throwErrnoIfMinus1 = throwErrnoIf (== -1)
332 -- as `throwErrnoIfMinus1', but discards the result
334 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
335 throwErrnoIfMinus1_ = throwErrnoIf_ (== -1)
337 -- throws "errno" if a result of "-1" is returned, but retries in case of an
338 -- interrupted operation
340 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
341 throwErrnoIfMinus1Retry = throwErrnoIfRetry (== -1)
343 -- as `throwErrnoIfMinus1', but discards the result
345 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
346 throwErrnoIfMinus1Retry_ = throwErrnoIfRetry_ (== -1)
348 -- throws "errno" if a result of a NULL pointer is returned
350 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
351 throwErrnoIfNull = throwErrnoIf (== nullPtr)
353 -- throws "errno" if a result of a NULL pointer is returned, but retries in
354 -- case of an interrupted operation
356 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
357 throwErrnoIfNullRetry = throwErrnoIfRetry (== nullPtr)
360 -- conversion of an "errno" value into IO error
361 -- --------------------------------------------
363 -- convert a location string, an "errno" value, an optional handle,
364 -- and an optional filename into a matching IO error
366 errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
367 errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do
368 str <- strerror errno >>= peekCString
369 #if __GLASGOW_HASKELL__
370 return (IOException (IOError maybeHdl errType loc str maybeName))
373 | errno == eOK = OtherError
374 | errno == e2BIG = ResourceExhausted
375 | errno == eACCES = PermissionDenied
376 | errno == eADDRINUSE = ResourceBusy
377 | errno == eADDRNOTAVAIL = UnsupportedOperation
378 | errno == eADV = OtherError
379 | errno == eAFNOSUPPORT = UnsupportedOperation
380 | errno == eAGAIN = ResourceExhausted
381 | errno == eALREADY = AlreadyExists
382 | errno == eBADF = OtherError
383 | errno == eBADMSG = InappropriateType
384 | errno == eBADRPC = OtherError
385 | errno == eBUSY = ResourceBusy
386 | errno == eCHILD = NoSuchThing
387 | errno == eCOMM = ResourceVanished
388 | errno == eCONNABORTED = OtherError
389 | errno == eCONNREFUSED = NoSuchThing
390 | errno == eCONNRESET = ResourceVanished
391 | errno == eDEADLK = ResourceBusy
392 | errno == eDESTADDRREQ = InvalidArgument
393 | errno == eDIRTY = UnsatisfiedConstraints
394 | errno == eDOM = InvalidArgument
395 | errno == eDQUOT = PermissionDenied
396 | errno == eEXIST = AlreadyExists
397 | errno == eFAULT = OtherError
398 | errno == eFBIG = PermissionDenied
399 | errno == eFTYPE = InappropriateType
400 | errno == eHOSTDOWN = NoSuchThing
401 | errno == eHOSTUNREACH = NoSuchThing
402 | errno == eIDRM = ResourceVanished
403 | errno == eILSEQ = InvalidArgument
404 | errno == eINPROGRESS = AlreadyExists
405 | errno == eINTR = Interrupted
406 | errno == eINVAL = InvalidArgument
407 | errno == eIO = HardwareFault
408 | errno == eISCONN = AlreadyExists
409 | errno == eISDIR = InappropriateType
410 | errno == eLOOP = InvalidArgument
411 | errno == eMFILE = ResourceExhausted
412 | errno == eMLINK = ResourceExhausted
413 | errno == eMSGSIZE = ResourceExhausted
414 | errno == eMULTIHOP = UnsupportedOperation
415 | errno == eNAMETOOLONG = InvalidArgument
416 | errno == eNETDOWN = ResourceVanished
417 | errno == eNETRESET = ResourceVanished
418 | errno == eNETUNREACH = NoSuchThing
419 | errno == eNFILE = ResourceExhausted
420 | errno == eNOBUFS = ResourceExhausted
421 | errno == eNODATA = NoSuchThing
422 | errno == eNODEV = NoSuchThing
423 | errno == eNOENT = NoSuchThing
424 | errno == eNOEXEC = InvalidArgument
425 | errno == eNOLCK = ResourceExhausted
426 | errno == eNOLINK = ResourceVanished
427 | errno == eNOMEM = ResourceExhausted
428 | errno == eNOMSG = NoSuchThing
429 | errno == eNONET = NoSuchThing
430 | errno == eNOPROTOOPT = UnsupportedOperation
431 | errno == eNOSPC = ResourceExhausted
432 | errno == eNOSR = ResourceExhausted
433 | errno == eNOSTR = InvalidArgument
434 | errno == eNOSYS = UnsupportedOperation
435 | errno == eNOTBLK = InvalidArgument
436 | errno == eNOTCONN = InvalidArgument
437 | errno == eNOTDIR = InappropriateType
438 | errno == eNOTEMPTY = UnsatisfiedConstraints
439 | errno == eNOTSOCK = InvalidArgument
440 | errno == eNOTTY = IllegalOperation
441 | errno == eNXIO = NoSuchThing
442 | errno == eOPNOTSUPP = UnsupportedOperation
443 | errno == ePERM = PermissionDenied
444 | errno == ePFNOSUPPORT = UnsupportedOperation
445 | errno == ePIPE = ResourceVanished
446 | errno == ePROCLIM = PermissionDenied
447 | errno == ePROCUNAVAIL = UnsupportedOperation
448 | errno == ePROGMISMATCH = ProtocolError
449 | errno == ePROGUNAVAIL = UnsupportedOperation
450 | errno == ePROTO = ProtocolError
451 | errno == ePROTONOSUPPORT = ProtocolError
452 | errno == ePROTOTYPE = ProtocolError
453 | errno == eRANGE = UnsupportedOperation
454 | errno == eREMCHG = ResourceVanished
455 | errno == eREMOTE = IllegalOperation
456 | errno == eROFS = PermissionDenied
457 | errno == eRPCMISMATCH = ProtocolError
458 | errno == eRREMOTE = IllegalOperation
459 | errno == eSHUTDOWN = IllegalOperation
460 | errno == eSOCKTNOSUPPORT = UnsupportedOperation
461 | errno == eSPIPE = UnsupportedOperation
462 | errno == eSRCH = NoSuchThing
463 | errno == eSRMNT = UnsatisfiedConstraints
464 | errno == eSTALE = ResourceVanished
465 | errno == eTIME = TimeExpired
466 | errno == eTIMEDOUT = TimeExpired
467 | errno == eTOOMANYREFS = ResourceExhausted
468 | errno == eTXTBSY = ResourceBusy
469 | errno == eUSERS = ResourceExhausted
470 | errno == eWOULDBLOCK = OtherError
471 | errno == eXDEV = UnsupportedOperation
472 | otherwise = OtherError
474 return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
477 foreign import unsafe strerror :: Errno -> IO (Ptr CChar)