757f43bea9180a0843245840062759fd4c20ced2
[ghc-hetmet.git] / ghc / lib / std / PrelCError.lhs
1 % -----------------------------------------------------------------------------
2 % $Id: PrelCError.lhs,v 1.2 2001/01/12 17:45:30 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 #-}
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   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 PrelIOBase
101 import PrelPtr
102 import PrelNum
103 import PrelShow
104 import PrelMaybe
105 import PrelBase
106 #else
107 import Ptr          (Ptr, nullPtr)
108 import CTypes       (CInt)
109 import MarshalError (void)
110
111 import IO           (IOError, Handle, ioError)
112 #endif
113
114 -- system dependent re-definitions
115 -- -------------------------------
116
117 -- we bring GHC's `IOErrorType' in scope in other compilers to simplify the
118 -- routine `errnoToIOError' below
119 --
120 #if !__GLASGOW_HASKELL__
121 data IOErrorType
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
131   | EOF
132 #endif
133
134
135 -- "errno" type
136 -- ------------
137
138 -- Haskell representation for "errno" values
139 --
140 newtype Errno = Errno CInt
141
142 instance Eq Errno where
143   errno1@(Errno no1) == errno2@(Errno no2) 
144     | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
145     | otherwise                                  = False
146
147 -- common "errno" symbols
148 --
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
163 --
164 -- the CCONST_XXX identifiers are cpp symbols whose value is computed by
165 -- configure 
166 --
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
265
266 -- checks whether the given errno value is supported on the current
267 -- architecture
268 --
269 isValidErrno               :: Errno -> Bool
270 --
271 -- the configure script sets all invalid "errno"s to 0
272 --
273 isValidErrno (Errno errno)  = errno /= 0
274
275
276 -- access to the current thread's "errno" value
277 -- --------------------------------------------
278
279 -- yield the current thread's "errno" value
280 --
281 getErrno :: IO Errno
282 getErrno  = liftM Errno (peek _errno)
283
284
285 -- set the current thread's "errno" value to 0
286 --
287 resetErrno :: IO ()
288 resetErrno  = poke _errno 0
289
290
291 -- throw current "errno" value
292 -- ---------------------------
293
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
296 --
297 throwErrno     :: String -> IO a
298 throwErrno loc  =
299   do
300     errno <- getErrno
301     ioError (errnoToIOError loc errno Nothing Nothing)
302
303
304 -- guards for IO operations that may fail
305 -- --------------------------------------
306
307 -- guard an IO operation and throw an "errno" based exception of the result
308 -- value of the IO operation meets the given predicate
309 --
310 throwErrnoIf            :: (a -> Bool) -> String -> IO a -> IO a
311 throwErrnoIf pred loc f  = 
312   do
313     res <- f
314     if pred res then throwErrno loc else return res
315
316 -- as `throwErrnoIf', but discards the result
317 --
318 throwErrnoIf_            :: (a -> Bool) -> String -> IO a -> IO ()
319 throwErrnoIf_ pred loc f  = void $ throwErrnoIf pred loc f
320
321 -- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
322 -- flag `EINTR')
323 --
324 throwErrnoIfRetry            :: (a -> Bool) -> String -> IO a -> IO a
325 throwErrnoIfRetry pred loc f  = 
326   do
327     res <- f
328     if pred res
329       then do
330         err <- getErrno
331         if err == eINTR
332           then throwErrnoIfRetry pred loc f
333           else throwErrno loc
334       else return res
335
336 -- as `throwErrnoIfRetry', but discards the result
337 --
338 throwErrnoIfRetry_            :: (a -> Bool) -> String -> IO a -> IO ()
339 throwErrnoIfRetry_ pred loc f  = void $ throwErrnoIfRetry pred loc f
340
341 -- throws "errno" if a result of "-1" is returned
342 --
343 throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
344 throwErrnoIfMinus1  = throwErrnoIf (== -1)
345
346 -- as `throwErrnoIfMinus1', but discards the result
347 --
348 throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
349 throwErrnoIfMinus1_  = throwErrnoIf_ (== -1)
350
351 -- throws "errno" if a result of "-1" is returned, but retries in case of an
352 -- interrupted operation
353 --
354 throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
355 throwErrnoIfMinus1Retry  = throwErrnoIfRetry (== -1)
356
357 -- as `throwErrnoIfMinus1', but discards the result
358 --
359 throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
360 throwErrnoIfMinus1Retry_  = throwErrnoIfRetry_ (== -1)
361
362 -- throws "errno" if a result of a NULL pointer is returned
363 --
364 throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
365 throwErrnoIfNull  = throwErrnoIf (== nullPtr)
366
367 -- throws "errno" if a result of a NULL pointer is returned, but retries in
368 -- case of an interrupted operation
369 --
370 throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
371 throwErrnoIfNullRetry  = throwErrnoIfRetry (== nullPtr)
372
373
374 -- conversion of an "errno" value into IO error
375 -- --------------------------------------------
376
377 -- convert a location string, an "errno" value, an optional handle,
378 -- and an optional filename into a matching IO error
379 --
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)
384 #else
385   userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName)
386 #endif
387   where
388     (errType, str)
389       | no == 0                   = (OtherError,
390                                      "no error")
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 " ++
403                                      "protocol family")
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,
416                                      "device busy")
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,
432                                      "file system dirty")
433       | errno == eDOM             = (InvalidArgument,
434                                      "argument too large")
435       | errno == eDQUOT           = (PermissionDenied,
436                                      "quota exceeded")
437       | errno == eEXIST           = (AlreadyExists,
438                                      "file already exists")
439       | errno == eFAULT           = (OtherError,
440                                      "internal error (EFAULT)")
441       | errno == eFBIG            = (PermissionDenied,
442                                      "file too large")
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,
458                                      "invalid argument")
459       | errno == eIO              = (HardwareFault,
460                                      "unknown I/O fault")
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,
470                                      "too many links")
471       | errno == eMSGSIZE         = (ResourceExhausted,
472                                      "message too long")
473       | errno == eMULTIHOP        = (UnsupportedOperation,
474                                      "multi-hop RFS request")
475       | errno == eNAMETOOLONG     = (InvalidArgument,
476                                      "filename too long")
477       | errno == eNETDOWN         = (ResourceVanished,
478                                      "network is down")
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 " ++
489                                      "queue")
490                                      -- no multiline strings with cpp
491       | errno == eNODEV           = (NoSuchThing,
492                                      "no such device")
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,
522                                      "not a directory")
523       | errno == eNOTEMPTY        = (UnsatisfiedConstraints,
524                                      "directory not empty")
525       | errno == eNOTSOCK         = (InvalidArgument,
526                                      "not a socket")
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,
538                                      "broken pipe")
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,
554                                      "result too large")
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,
564                                      "object is remote")
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,
572                                      "no such process")
573       | errno == eSRMNT           = (UnsatisfiedConstraints,
574                                      "RFS resources still mounted by " ++
575                                      "remote host(s)")
576                                      -- no multiline strings with cpp
577       | errno == eSTALE           = (ResourceVanished,
578                                      "stale NFS file handle")
579       | errno == eTIME            = (TimeExpired,
580                                      "timer expired")
581       | errno == eTIMEDOUT        = (TimeExpired,
582                                      "connection timed out")
583       | errno == eTOOMANYREFS     = (ResourceExhausted,
584                                      "too many references; can't splice")
585       | errno == eTXTBSY          = (ResourceBusy,
586                                      "text file in-use")
587       | errno == eUSERS           = (ResourceExhausted,
588                                      "quota table full")
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: " 
595                                      ++ show no ++")")
596
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 
601 \end{code}