1 {-# OPTIONS -fno-implicit-prelude -#include "HsCore.h" #-}
2 -----------------------------------------------------------------------------
4 -- Module : Foreign.C.Error
5 -- Copyright : (c) The FFI task force 2001
6 -- License : BSD-style (see the file libraries/core/LICENSE)
8 -- Maintainer : ffi@haskell.org
9 -- Stability : provisional
10 -- Portability : portable
12 -- $Id: Error.hs,v 1.2 2001/07/03 11:37:50 simonmar Exp $
14 -- C-specific Marshalling support: Handling of C "errno" error codes
16 -----------------------------------------------------------------------------
18 module Foreign.C.Error (
20 -- Haskell representation for "errno" values
22 Errno(..), -- instance: Eq
23 eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
24 eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
25 eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
26 eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
27 eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
28 eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
29 eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
30 eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
31 eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,
32 eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
33 ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
34 eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
35 eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
36 eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,
38 isValidErrno, -- :: Errno -> Bool
40 -- access to the current thread's "errno" value
42 getErrno, -- :: IO Errno
43 resetErrno, -- :: IO ()
45 -- conversion of an "errno" value into IO error
47 errnoToIOError, -- :: String -- location
49 -- -> Maybe Handle -- handle
50 -- -> Maybe String -- filename
53 -- throw current "errno" value
55 throwErrno, -- :: String -> IO a
57 -- guards for IO operations that may fail
59 throwErrnoIf, -- :: (a -> Bool) -> String -> IO a -> IO a
60 throwErrnoIf_, -- :: (a -> Bool) -> String -> IO a -> IO ()
61 throwErrnoIfRetry, -- :: (a -> Bool) -> String -> IO a -> IO a
62 throwErrnoIfRetry_, -- :: (a -> Bool) -> String -> IO a -> IO ()
63 throwErrnoIfMinus1, -- :: Num a
64 -- => String -> IO a -> IO a
65 throwErrnoIfMinus1_, -- :: Num a
66 -- => String -> IO a -> IO ()
67 throwErrnoIfMinus1Retry,
69 -- => String -> IO a -> IO a
70 throwErrnoIfMinus1Retry_,
72 -- => String -> IO a -> IO ()
73 throwErrnoIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)
74 throwErrnoIfNullRetry,-- :: String -> IO (Ptr a) -> IO (Ptr a)
76 throwErrnoIfRetryMayBlock,
77 throwErrnoIfRetryMayBlock_,
78 throwErrnoIfMinus1RetryMayBlock,
79 throwErrnoIfMinus1RetryMayBlock_,
80 throwErrnoIfNullRetryMayBlock
84 -- 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 (Exception(..), IOException(..), IOErrorType(..))
96 #endif /* __GLASGOW_HASKELL__ */
103 import Foreign.C.Types
104 import Foreign.C.String
105 import Foreign.Marshal.Error ( void )
108 #if __GLASGOW_HASKELL__
114 import System.IO ( IOError, Handle, ioError )
120 -- import of C function that gives address of errno
122 foreign import "ghcErrno" unsafe _errno :: Ptr CInt
124 -- Haskell representation for "errno" values
126 newtype Errno = Errno CInt
128 instance Eq Errno where
129 errno1@(Errno no1) == errno2@(Errno no2)
130 | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
133 -- common "errno" symbols
135 eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
136 eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
137 eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
138 eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
139 eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
140 eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
141 eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
142 eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
143 eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,
144 eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
145 ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
146 eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
147 eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
148 eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV :: Errno
150 -- the CCONST_XXX identifiers are cpp symbols whose value is computed by
154 e2BIG = Errno (CCONST_E2BIG)
155 eACCES = Errno (CCONST_EACCES)
156 eADDRINUSE = Errno (CCONST_EADDRINUSE)
157 eADDRNOTAVAIL = Errno (CCONST_EADDRNOTAVAIL)
158 eADV = Errno (CCONST_EADV)
159 eAFNOSUPPORT = Errno (CCONST_EAFNOSUPPORT)
160 eAGAIN = Errno (CCONST_EAGAIN)
161 eALREADY = Errno (CCONST_EALREADY)
162 eBADF = Errno (CCONST_EBADF)
163 eBADMSG = Errno (CCONST_EBADMSG)
164 eBADRPC = Errno (CCONST_EBADRPC)
165 eBUSY = Errno (CCONST_EBUSY)
166 eCHILD = Errno (CCONST_ECHILD)
167 eCOMM = Errno (CCONST_ECOMM)
168 eCONNABORTED = Errno (CCONST_ECONNABORTED)
169 eCONNREFUSED = Errno (CCONST_ECONNREFUSED)
170 eCONNRESET = Errno (CCONST_ECONNRESET)
171 eDEADLK = Errno (CCONST_EDEADLK)
172 eDESTADDRREQ = Errno (CCONST_EDESTADDRREQ)
173 eDIRTY = Errno (CCONST_EDIRTY)
174 eDOM = Errno (CCONST_EDOM)
175 eDQUOT = Errno (CCONST_EDQUOT)
176 eEXIST = Errno (CCONST_EEXIST)
177 eFAULT = Errno (CCONST_EFAULT)
178 eFBIG = Errno (CCONST_EFBIG)
179 eFTYPE = Errno (CCONST_EFTYPE)
180 eHOSTDOWN = Errno (CCONST_EHOSTDOWN)
181 eHOSTUNREACH = Errno (CCONST_EHOSTUNREACH)
182 eIDRM = Errno (CCONST_EIDRM)
183 eILSEQ = Errno (CCONST_EILSEQ)
184 eINPROGRESS = Errno (CCONST_EINPROGRESS)
185 eINTR = Errno (CCONST_EINTR)
186 eINVAL = Errno (CCONST_EINVAL)
187 eIO = Errno (CCONST_EIO)
188 eISCONN = Errno (CCONST_EISCONN)
189 eISDIR = Errno (CCONST_EISDIR)
190 eLOOP = Errno (CCONST_ELOOP)
191 eMFILE = Errno (CCONST_EMFILE)
192 eMLINK = Errno (CCONST_EMLINK)
193 eMSGSIZE = Errno (CCONST_EMSGSIZE)
194 eMULTIHOP = Errno (CCONST_EMULTIHOP)
195 eNAMETOOLONG = Errno (CCONST_ENAMETOOLONG)
196 eNETDOWN = Errno (CCONST_ENETDOWN)
197 eNETRESET = Errno (CCONST_ENETRESET)
198 eNETUNREACH = Errno (CCONST_ENETUNREACH)
199 eNFILE = Errno (CCONST_ENFILE)
200 eNOBUFS = Errno (CCONST_ENOBUFS)
201 eNODATA = Errno (CCONST_ENODATA)
202 eNODEV = Errno (CCONST_ENODEV)
203 eNOENT = Errno (CCONST_ENOENT)
204 eNOEXEC = Errno (CCONST_ENOEXEC)
205 eNOLCK = Errno (CCONST_ENOLCK)
206 eNOLINK = Errno (CCONST_ENOLINK)
207 eNOMEM = Errno (CCONST_ENOMEM)
208 eNOMSG = Errno (CCONST_ENOMSG)
209 eNONET = Errno (CCONST_ENONET)
210 eNOPROTOOPT = Errno (CCONST_ENOPROTOOPT)
211 eNOSPC = Errno (CCONST_ENOSPC)
212 eNOSR = Errno (CCONST_ENOSR)
213 eNOSTR = Errno (CCONST_ENOSTR)
214 eNOSYS = Errno (CCONST_ENOSYS)
215 eNOTBLK = Errno (CCONST_ENOTBLK)
216 eNOTCONN = Errno (CCONST_ENOTCONN)
217 eNOTDIR = Errno (CCONST_ENOTDIR)
218 eNOTEMPTY = Errno (CCONST_ENOTEMPTY)
219 eNOTSOCK = Errno (CCONST_ENOTSOCK)
220 eNOTTY = Errno (CCONST_ENOTTY)
221 eNXIO = Errno (CCONST_ENXIO)
222 eOPNOTSUPP = Errno (CCONST_EOPNOTSUPP)
223 ePERM = Errno (CCONST_EPERM)
224 ePFNOSUPPORT = Errno (CCONST_EPFNOSUPPORT)
225 ePIPE = Errno (CCONST_EPIPE)
226 ePROCLIM = Errno (CCONST_EPROCLIM)
227 ePROCUNAVAIL = Errno (CCONST_EPROCUNAVAIL)
228 ePROGMISMATCH = Errno (CCONST_EPROGMISMATCH)
229 ePROGUNAVAIL = Errno (CCONST_EPROGUNAVAIL)
230 ePROTO = Errno (CCONST_EPROTO)
231 ePROTONOSUPPORT = Errno (CCONST_EPROTONOSUPPORT)
232 ePROTOTYPE = Errno (CCONST_EPROTOTYPE)
233 eRANGE = Errno (CCONST_ERANGE)
234 eREMCHG = Errno (CCONST_EREMCHG)
235 eREMOTE = Errno (CCONST_EREMOTE)
236 eROFS = Errno (CCONST_EROFS)
237 eRPCMISMATCH = Errno (CCONST_ERPCMISMATCH)
238 eRREMOTE = Errno (CCONST_ERREMOTE)
239 eSHUTDOWN = Errno (CCONST_ESHUTDOWN)
240 eSOCKTNOSUPPORT = Errno (CCONST_ESOCKTNOSUPPORT)
241 eSPIPE = Errno (CCONST_ESPIPE)
242 eSRCH = Errno (CCONST_ESRCH)
243 eSRMNT = Errno (CCONST_ESRMNT)
244 eSTALE = Errno (CCONST_ESTALE)
245 eTIME = Errno (CCONST_ETIME)
246 eTIMEDOUT = Errno (CCONST_ETIMEDOUT)
247 eTOOMANYREFS = Errno (CCONST_ETOOMANYREFS)
248 eTXTBSY = Errno (CCONST_ETXTBSY)
249 eUSERS = Errno (CCONST_EUSERS)
250 eWOULDBLOCK = Errno (CCONST_EWOULDBLOCK)
251 eXDEV = Errno (CCONST_EXDEV)
253 -- checks whether the given errno value is supported on the current
256 isValidErrno :: Errno -> Bool
258 -- the configure script sets all invalid "errno"s to -1
260 isValidErrno (Errno errno) = errno /= -1
263 -- access to the current thread's "errno" value
264 -- --------------------------------------------
266 -- yield the current thread's "errno" value
269 getErrno = do e <- peek _errno; return (Errno e)
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 checks for operations that would block and
323 -- executes an alternative action in that case.
325 throwErrnoIfRetryMayBlock :: (a -> Bool) -> String -> IO a -> IO b -> IO a
326 throwErrnoIfRetryMayBlock pred loc f on_block =
333 then throwErrnoIfRetryMayBlock pred loc f on_block
334 else if err == eWOULDBLOCK || err == eAGAIN
335 then do on_block; throwErrnoIfRetryMayBlock pred loc f on_block
339 -- as `throwErrnoIfRetry', but discards the result
341 throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO ()
342 throwErrnoIfRetry_ pred loc f = void $ throwErrnoIfRetry pred loc f
344 -- as `throwErrnoIfRetryMayBlock', but discards the result
346 throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO ()
347 throwErrnoIfRetryMayBlock_ pred loc f on_block
348 = void $ throwErrnoIfRetryMayBlock pred loc f on_block
350 -- throws "errno" if a result of "-1" is returned
352 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
353 throwErrnoIfMinus1 = throwErrnoIf (== -1)
355 -- as `throwErrnoIfMinus1', but discards the result
357 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
358 throwErrnoIfMinus1_ = throwErrnoIf_ (== -1)
360 -- throws "errno" if a result of "-1" is returned, but retries in case of an
361 -- interrupted operation
363 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
364 throwErrnoIfMinus1Retry = throwErrnoIfRetry (== -1)
366 -- as `throwErrnoIfMinus1', but discards the result
368 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
369 throwErrnoIfMinus1Retry_ = throwErrnoIfRetry_ (== -1)
371 -- as throwErrnoIfMinus1Retry, but checks for operations that would block
373 throwErrnoIfMinus1RetryMayBlock :: Num a => String -> IO a -> IO b -> IO a
374 throwErrnoIfMinus1RetryMayBlock = throwErrnoIfRetryMayBlock (== -1)
376 -- as `throwErrnoIfMinus1RetryMayBlock', but discards the result
378 throwErrnoIfMinus1RetryMayBlock_ :: Num a => String -> IO a -> IO b -> IO ()
379 throwErrnoIfMinus1RetryMayBlock_ = throwErrnoIfRetryMayBlock_ (== -1)
381 -- throws "errno" if a result of a NULL pointer is returned
383 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
384 throwErrnoIfNull = throwErrnoIf (== nullPtr)
386 -- throws "errno" if a result of a NULL pointer is returned, but retries in
387 -- case of an interrupted operation
389 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
390 throwErrnoIfNullRetry = throwErrnoIfRetry (== nullPtr)
392 -- as throwErrnoIfNullRetry, but checks for operations that would block
394 throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)
395 throwErrnoIfNullRetryMayBlock = throwErrnoIfRetryMayBlock (== nullPtr)
397 -- conversion of an "errno" value into IO error
398 -- --------------------------------------------
400 -- convert a location string, an "errno" value, an optional handle,
401 -- and an optional filename into a matching IO error
403 errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
404 errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do
405 str <- strerror errno >>= peekCString
406 #if __GLASGOW_HASKELL__
407 return (IOException (IOError maybeHdl errType loc str maybeName))
410 | errno == eOK = OtherError
411 | errno == e2BIG = ResourceExhausted
412 | errno == eACCES = PermissionDenied
413 | errno == eADDRINUSE = ResourceBusy
414 | errno == eADDRNOTAVAIL = UnsupportedOperation
415 | errno == eADV = OtherError
416 | errno == eAFNOSUPPORT = UnsupportedOperation
417 | errno == eAGAIN = ResourceExhausted
418 | errno == eALREADY = AlreadyExists
419 | errno == eBADF = OtherError
420 | errno == eBADMSG = InappropriateType
421 | errno == eBADRPC = OtherError
422 | errno == eBUSY = ResourceBusy
423 | errno == eCHILD = NoSuchThing
424 | errno == eCOMM = ResourceVanished
425 | errno == eCONNABORTED = OtherError
426 | errno == eCONNREFUSED = NoSuchThing
427 | errno == eCONNRESET = ResourceVanished
428 | errno == eDEADLK = ResourceBusy
429 | errno == eDESTADDRREQ = InvalidArgument
430 | errno == eDIRTY = UnsatisfiedConstraints
431 | errno == eDOM = InvalidArgument
432 | errno == eDQUOT = PermissionDenied
433 | errno == eEXIST = AlreadyExists
434 | errno == eFAULT = OtherError
435 | errno == eFBIG = PermissionDenied
436 | errno == eFTYPE = InappropriateType
437 | errno == eHOSTDOWN = NoSuchThing
438 | errno == eHOSTUNREACH = NoSuchThing
439 | errno == eIDRM = ResourceVanished
440 | errno == eILSEQ = InvalidArgument
441 | errno == eINPROGRESS = AlreadyExists
442 | errno == eINTR = Interrupted
443 | errno == eINVAL = InvalidArgument
444 | errno == eIO = HardwareFault
445 | errno == eISCONN = AlreadyExists
446 | errno == eISDIR = InappropriateType
447 | errno == eLOOP = InvalidArgument
448 | errno == eMFILE = ResourceExhausted
449 | errno == eMLINK = ResourceExhausted
450 | errno == eMSGSIZE = ResourceExhausted
451 | errno == eMULTIHOP = UnsupportedOperation
452 | errno == eNAMETOOLONG = InvalidArgument
453 | errno == eNETDOWN = ResourceVanished
454 | errno == eNETRESET = ResourceVanished
455 | errno == eNETUNREACH = NoSuchThing
456 | errno == eNFILE = ResourceExhausted
457 | errno == eNOBUFS = ResourceExhausted
458 | errno == eNODATA = NoSuchThing
459 | errno == eNODEV = NoSuchThing
460 | errno == eNOENT = NoSuchThing
461 | errno == eNOEXEC = InvalidArgument
462 | errno == eNOLCK = ResourceExhausted
463 | errno == eNOLINK = ResourceVanished
464 | errno == eNOMEM = ResourceExhausted
465 | errno == eNOMSG = NoSuchThing
466 | errno == eNONET = NoSuchThing
467 | errno == eNOPROTOOPT = UnsupportedOperation
468 | errno == eNOSPC = ResourceExhausted
469 | errno == eNOSR = ResourceExhausted
470 | errno == eNOSTR = InvalidArgument
471 | errno == eNOSYS = UnsupportedOperation
472 | errno == eNOTBLK = InvalidArgument
473 | errno == eNOTCONN = InvalidArgument
474 | errno == eNOTDIR = InappropriateType
475 | errno == eNOTEMPTY = UnsatisfiedConstraints
476 | errno == eNOTSOCK = InvalidArgument
477 | errno == eNOTTY = IllegalOperation
478 | errno == eNXIO = NoSuchThing
479 | errno == eOPNOTSUPP = UnsupportedOperation
480 | errno == ePERM = PermissionDenied
481 | errno == ePFNOSUPPORT = UnsupportedOperation
482 | errno == ePIPE = ResourceVanished
483 | errno == ePROCLIM = PermissionDenied
484 | errno == ePROCUNAVAIL = UnsupportedOperation
485 | errno == ePROGMISMATCH = ProtocolError
486 | errno == ePROGUNAVAIL = UnsupportedOperation
487 | errno == ePROTO = ProtocolError
488 | errno == ePROTONOSUPPORT = ProtocolError
489 | errno == ePROTOTYPE = ProtocolError
490 | errno == eRANGE = UnsupportedOperation
491 | errno == eREMCHG = ResourceVanished
492 | errno == eREMOTE = IllegalOperation
493 | errno == eROFS = PermissionDenied
494 | errno == eRPCMISMATCH = ProtocolError
495 | errno == eRREMOTE = IllegalOperation
496 | errno == eSHUTDOWN = IllegalOperation
497 | errno == eSOCKTNOSUPPORT = UnsupportedOperation
498 | errno == eSPIPE = UnsupportedOperation
499 | errno == eSRCH = NoSuchThing
500 | errno == eSRMNT = UnsatisfiedConstraints
501 | errno == eSTALE = ResourceVanished
502 | errno == eTIME = TimeExpired
503 | errno == eTIMEDOUT = TimeExpired
504 | errno == eTOOMANYREFS = ResourceExhausted
505 | errno == eTXTBSY = ResourceBusy
506 | errno == eUSERS = ResourceExhausted
507 | errno == eWOULDBLOCK = OtherError
508 | errno == eXDEV = UnsupportedOperation
509 | otherwise = OtherError
511 return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
514 foreign import unsafe strerror :: Errno -> IO (Ptr CChar)