[project @ 2001-03-23 16:36:20 by simonmar]
[ghc-hetmet.git] / ghc / lib / std / PrelCError.lhs
1 % -----------------------------------------------------------------------------
2 % $Id: PrelCError.lhs,v 1.7 2001/03/16 21:47:41 qrczak Exp $
3 %
4 % (c) The FFI task force, 2000
5 %
6
7 C-specific Marshalling support: Handling of C "errno" error codes
8
9 \begin{code}
10 {-# OPTIONS -fno-implicit-prelude -#include "cbits/ghc_errno.h" #-}
11
12 -- this is were we get the CCONST_XXX definitions from that configure
13 -- calculated for us
14 --
15 #include "config.h"
16
17 module PrelCError (
18
19   -- Haskell representation for "errno" values
20   --
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,
36                         -- :: Errno
37   isValidErrno,         -- :: Errno -> Bool
38
39   -- access to the current thread's "errno" value
40   --
41   getErrno,             -- :: IO Errno
42   resetErrno,           -- :: IO ()
43
44   -- conversion of an "errno" value into IO error
45   --
46   errnoToIOError,       -- :: String       -- location
47                         -- -> Errno        -- errno
48                         -- -> Maybe Handle -- handle
49                         -- -> Maybe String -- filename
50                         -- -> IOError
51
52   -- throw current "errno" value
53   --
54   throwErrno,           -- ::                String               -> IO a
55
56   -- guards for IO operations that may fail
57   --
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,  
67                         -- :: Num a 
68                         -- =>                String -> IO a       -> IO a
69   throwErrnoIfMinus1Retry_,  
70                         -- :: Num a 
71                         -- =>                String -> IO a       -> IO ()
72   throwErrnoIfNull,     -- ::                String -> IO (Ptr a) -> IO (Ptr a)
73   throwErrnoIfNullRetry -- ::                String -> IO (Ptr a) -> IO (Ptr a)
74 ) where
75
76
77 -- system dependent imports
78 -- ------------------------
79
80 -- GHC allows us to get at the guts inside IO errors/exceptions
81 --
82 #if __GLASGOW_HASKELL__
83 #if __GLASGOW_HASKELL__ < 409
84 import PrelIOBase (IOError(..), IOErrorType(..))
85 #else
86 import PrelIOBase (Exception(..), IOException(..), IOErrorType(..))
87 #endif
88 #endif /* __GLASGOW_HASKELL__ */
89
90
91 -- regular imports
92 -- ---------------
93
94 import Monad        (liftM)
95
96 #if __GLASGOW_HASKELL__
97 import PrelStorable
98 import PrelMarshalError
99 import PrelCTypes
100 import PrelCString
101 import PrelIOBase
102 import PrelPtr
103 import PrelNum
104 import PrelShow
105 import PrelMaybe
106 import PrelBase
107 #else
108 import Ptr          (Ptr, nullPtr)
109 import CTypes       (CInt)
110 import CString      (peekCString)
111 import MarshalError (void)
112
113 import IO           (IOError, Handle, ioError)
114 #endif
115
116 -- "errno" type
117 -- ------------
118
119 -- import of C function that gives address of errno
120 --
121 foreign import "ghcErrno" unsafe _errno :: Ptr CInt
122
123 -- Haskell representation for "errno" values
124 --
125 newtype Errno = Errno CInt
126
127 instance Eq Errno where
128   errno1@(Errno no1) == errno2@(Errno no2) 
129     | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
130     | otherwise                                  = False
131
132 -- common "errno" symbols
133 --
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
148 --
149 -- the CCONST_XXX identifiers are cpp symbols whose value is computed by
150 -- configure 
151 --
152 eOK             = Errno 0
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)
251
252 -- checks whether the given errno value is supported on the current
253 -- architecture
254 --
255 isValidErrno               :: Errno -> Bool
256 --
257 -- the configure script sets all invalid "errno"s to -1
258 --
259 isValidErrno (Errno errno)  = errno /= -1
260
261
262 -- access to the current thread's "errno" value
263 -- --------------------------------------------
264
265 -- yield the current thread's "errno" value
266 --
267 getErrno :: IO Errno
268 getErrno  = liftM Errno (peek _errno)
269
270
271 -- set the current thread's "errno" value to 0
272 --
273 resetErrno :: IO ()
274 resetErrno  = poke _errno 0
275
276
277 -- throw current "errno" value
278 -- ---------------------------
279
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
282 --
283 throwErrno     :: String -> IO a
284 throwErrno loc  =
285   do
286     errno <- getErrno
287     ioError (errnoToIOError loc errno Nothing Nothing)
288
289
290 -- guards for IO operations that may fail
291 -- --------------------------------------
292
293 -- guard an IO operation and throw an "errno" based exception of the result
294 -- value of the IO operation meets the given predicate
295 --
296 throwErrnoIf            :: (a -> Bool) -> String -> IO a -> IO a
297 throwErrnoIf pred loc f  = 
298   do
299     res <- f
300     if pred res then throwErrno loc else return res
301
302 -- as `throwErrnoIf', but discards the result
303 --
304 throwErrnoIf_            :: (a -> Bool) -> String -> IO a -> IO ()
305 throwErrnoIf_ pred loc f  = void $ throwErrnoIf pred loc f
306
307 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
308 -- flag `EINTR')
309 --
310 throwErrnoIfRetry            :: (a -> Bool) -> String -> IO a -> IO a
311 throwErrnoIfRetry pred loc f  = 
312   do
313     res <- f
314     if pred res
315       then do
316         err <- getErrno
317         if err == eINTR
318           then throwErrnoIfRetry pred loc f
319           else throwErrno loc
320       else return res
321
322 -- as `throwErrnoIfRetry', but discards the result
323 --
324 throwErrnoIfRetry_            :: (a -> Bool) -> String -> IO a -> IO ()
325 throwErrnoIfRetry_ pred loc f  = void $ throwErrnoIfRetry pred loc f
326
327 -- throws "errno" if a result of "-1" is returned
328 --
329 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
330 throwErrnoIfMinus1  = throwErrnoIf (== -1)
331
332 -- as `throwErrnoIfMinus1', but discards the result
333 --
334 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
335 throwErrnoIfMinus1_  = throwErrnoIf_ (== -1)
336
337 -- throws "errno" if a result of "-1" is returned, but retries in case of an
338 -- interrupted operation
339 --
340 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
341 throwErrnoIfMinus1Retry  = throwErrnoIfRetry (== -1)
342
343 -- as `throwErrnoIfMinus1', but discards the result
344 --
345 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
346 throwErrnoIfMinus1Retry_  = throwErrnoIfRetry_ (== -1)
347
348 -- throws "errno" if a result of a NULL pointer is returned
349 --
350 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
351 throwErrnoIfNull  = throwErrnoIf (== nullPtr)
352
353 -- throws "errno" if a result of a NULL pointer is returned, but retries in
354 -- case of an interrupted operation
355 --
356 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
357 throwErrnoIfNullRetry  = throwErrnoIfRetry (== nullPtr)
358
359
360 -- conversion of an "errno" value into IO error
361 -- --------------------------------------------
362
363 -- convert a location string, an "errno" value, an optional handle,
364 -- and an optional filename into a matching IO error
365 --
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))
371     where
372     errType
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
473 #else
474     return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
475 #endif
476
477 foreign import unsafe strerror :: Errno -> IO (Ptr CChar)
478 \end{code}