    {-# LANGUAGE Trustworthy #-}
    {-# LANGUAGE CPP, NoImplicitPrelude #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Foreign.C.Error
    -- Copyright   :  (c) The FFI task force 2001
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  ffi@haskell.org
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -- C-specific Marshalling support: Handling of C \"errno\" error codes.
    --
    -----------------------------------------------------------------------------

    module Foreign.C.Error (

      -- * Haskell representations of @errno@ values

      Errno(..),

      -- ** Common @errno@ symbols
      -- | Different operating systems and\/or C libraries often support
      -- different values of @errno@.  This module defines the common values,
      -- but due to the open definition of 'Errno' users may add definitions
      -- which are not predefined.
      eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
      eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
      eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
      eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
      eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
      eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
      eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
      eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
      eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTSUP, eNOTTY, eNXIO,
      eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
      ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
      eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
      eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
      eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,

      -- ** 'Errno' functions
      isValidErrno,

      -- access to the current thread's "errno" value
      --
      getErrno,
      resetErrno,

      -- conversion of an "errno" value into IO error
      --
      errnoToIOError,

      -- throw current "errno" value
      --
      throwErrno,

      -- ** Guards for IO operations that may fail

      throwErrnoIf,
      throwErrnoIf_,
      throwErrnoIfRetry,
      throwErrnoIfRetry_,
      throwErrnoIfMinus1,
      throwErrnoIfMinus1_,
      throwErrnoIfMinus1Retry,
      throwErrnoIfMinus1Retry_,
      throwErrnoIfNull,
      throwErrnoIfNullRetry,

      throwErrnoIfRetryMayBlock,
      throwErrnoIfRetryMayBlock_,
      throwErrnoIfMinus1RetryMayBlock,
      throwErrnoIfMinus1RetryMayBlock_,
      throwErrnoIfNullRetryMayBlock,

      throwErrnoPath,
      throwErrnoPathIf,
      throwErrnoPathIf_,
      throwErrnoPathIfNull,
      throwErrnoPathIfMinus1,
      throwErrnoPathIfMinus1_,
    ) where

    -- this is were we get the CONST_XXX definitions from that configure
    -- calculated for us
    --
    #include "HsBaseConfig.h"

    import Foreign.Ptr
    import Foreign.C.Types
    import Foreign.C.String
    import Data.Functor            ( void )
    import Data.Maybe

    import GHC.IO
    import GHC.IO.Exception
    import GHC.IO.Handle.Types
    import GHC.Num
    import GHC.Base

    -- "errno" type
    -- ------------

    -- | Haskell representation for @errno@ values.
    -- The implementation is deliberately exposed, to allow users to add
    -- their own definitions of 'Errno' values.

    newtype Errno = Errno CInt

    -- | @since 2.01
    instance Eq Errno where
      errno1 :: Errno
    errno1@(Errno CInt
    no1) == :: Errno -> Errno -> Bool
    == errno2 :: Errno
    errno2@(Errno CInt
    no2)
        | Errno -> Bool
    isValidErrno Errno
    errno1 Bool -> Bool -> Bool
    && Errno -> Bool
    isValidErrno Errno
    errno2 = CInt
    no1 CInt -> CInt -> Bool
    forall a. Eq a => a -> a -> Bool
    == CInt
    no2
        | Bool
    otherwise                                  = Bool
    False

    -- common "errno" symbols
    --
    eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
      eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
      eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
      eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
      eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
      eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
      eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
      eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
      eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTSUP, eNOTTY, eNXIO,
      eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
      ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
      eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
      eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
      eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV                    :: Errno
    --
    -- the cCONST_XXX identifiers are cpp symbols whose value is computed by
    -- configure
    --
    eOK :: Errno
    eOK             = CInt -> Errno
    Errno CInt
    0
    e2BIG :: Errno
    e2BIG           = CInt -> Errno
    Errno (CONST_E2BIG)
    eACCES :: Errno
    eACCES          = CInt -> Errno
    Errno (CONST_EACCES)
    eADDRINUSE :: Errno
    eADDRINUSE      = CInt -> Errno
    Errno (CONST_EADDRINUSE)
    eADDRNOTAVAIL :: Errno
    eADDRNOTAVAIL   = CInt -> Errno
    Errno (CONST_EADDRNOTAVAIL)
    eADV :: Errno
    eADV            = CInt -> Errno
    Errno (CONST_EADV)
    eAFNOSUPPORT :: Errno
    eAFNOSUPPORT    = CInt -> Errno
    Errno (CONST_EAFNOSUPPORT)
    eAGAIN :: Errno
    eAGAIN          = CInt -> Errno
    Errno (CONST_EAGAIN)
    eALREADY :: Errno
    eALREADY        = CInt -> Errno
    Errno (CONST_EALREADY)
    eBADF :: Errno
    eBADF           = CInt -> Errno
    Errno (CONST_EBADF)
    eBADMSG :: Errno
    eBADMSG         = CInt -> Errno
    Errno (CONST_EBADMSG)
    eBADRPC :: Errno
    eBADRPC         = CInt -> Errno
    Errno (CONST_EBADRPC)
    eBUSY :: Errno
    eBUSY           = CInt -> Errno
    Errno (CONST_EBUSY)
    eCHILD :: Errno
    eCHILD          = CInt -> Errno
    Errno (CONST_ECHILD)
    eCOMM :: Errno
    eCOMM           = CInt -> Errno
    Errno (CONST_ECOMM)
    eCONNABORTED :: Errno
    eCONNABORTED    = CInt -> Errno
    Errno (CONST_ECONNABORTED)
    eCONNREFUSED :: Errno
    eCONNREFUSED    = CInt -> Errno
    Errno (CONST_ECONNREFUSED)
    eCONNRESET :: Errno
    eCONNRESET      = CInt -> Errno
    Errno (CONST_ECONNRESET)
    eDEADLK :: Errno
    eDEADLK         = CInt -> Errno
    Errno (CONST_EDEADLK)
    eDESTADDRREQ :: Errno
    eDESTADDRREQ    = CInt -> Errno
    Errno (CONST_EDESTADDRREQ)
    eDIRTY :: Errno
    eDIRTY          = CInt -> Errno
    Errno (CONST_EDIRTY)
    eDOM :: Errno
    eDOM            = CInt -> Errno
    Errno (CONST_EDOM)
    eDQUOT :: Errno
    eDQUOT          = CInt -> Errno
    Errno (CONST_EDQUOT)
    eEXIST :: Errno
    eEXIST          = CInt -> Errno
    Errno (CONST_EEXIST)
    eFAULT :: Errno
    eFAULT          = CInt -> Errno
    Errno (CONST_EFAULT)
    eFBIG :: Errno
    eFBIG           = CInt -> Errno
    Errno (CONST_EFBIG)
    eFTYPE :: Errno
    eFTYPE          = CInt -> Errno
    Errno (CONST_EFTYPE)
    eHOSTDOWN :: Errno
    eHOSTDOWN       = CInt -> Errno
    Errno (CONST_EHOSTDOWN)
    eHOSTUNREACH :: Errno
    eHOSTUNREACH    = CInt -> Errno
    Errno (CONST_EHOSTUNREACH)
    eIDRM :: Errno
    eIDRM           = CInt -> Errno
    Errno (CONST_EIDRM)
    eILSEQ :: Errno
    eILSEQ          = CInt -> Errno
    Errno (CONST_EILSEQ)
    eINPROGRESS :: Errno
    eINPROGRESS     = CInt -> Errno
    Errno (CONST_EINPROGRESS)
    eINTR :: Errno
    eINTR           = CInt -> Errno
    Errno (CONST_EINTR)
    eINVAL :: Errno
    eINVAL          = CInt -> Errno
    Errno (CONST_EINVAL)
    eIO :: Errno
    eIO             = CInt -> Errno
    Errno (CONST_EIO)
    eISCONN :: Errno
    eISCONN         = CInt -> Errno
    Errno (CONST_EISCONN)
    eISDIR :: Errno
    eISDIR          = CInt -> Errno
    Errno (CONST_EISDIR)
    eLOOP :: Errno
    eLOOP           = CInt -> Errno
    Errno (CONST_ELOOP)
    eMFILE :: Errno
    eMFILE          = CInt -> Errno
    Errno (CONST_EMFILE)
    eMLINK :: Errno
    eMLINK          = CInt -> Errno
    Errno (CONST_EMLINK)
    eMSGSIZE :: Errno
    eMSGSIZE        = CInt -> Errno
    Errno (CONST_EMSGSIZE)
    eMULTIHOP :: Errno
    eMULTIHOP       = CInt -> Errno
    Errno (CONST_EMULTIHOP)
    eNAMETOOLONG :: Errno
    eNAMETOOLONG    = CInt -> Errno
    Errno (CONST_ENAMETOOLONG)
    eNETDOWN :: Errno
    eNETDOWN        = CInt -> Errno
    Errno (CONST_ENETDOWN)
    eNETRESET :: Errno
    eNETRESET       = CInt -> Errno
    Errno (CONST_ENETRESET)
    eNETUNREACH :: Errno
    eNETUNREACH     = CInt -> Errno
    Errno (CONST_ENETUNREACH)
    eNFILE :: Errno
    eNFILE          = CInt -> Errno
    Errno (CONST_ENFILE)
    eNOBUFS :: Errno
    eNOBUFS         = CInt -> Errno
    Errno (CONST_ENOBUFS)
    eNODATA :: Errno
    eNODATA         = CInt -> Errno
    Errno (CONST_ENODATA)
    eNODEV :: Errno
    eNODEV          = CInt -> Errno
    Errno (CONST_ENODEV)
    eNOENT :: Errno
    eNOENT          = CInt -> Errno
    Errno (CONST_ENOENT)
    eNOEXEC :: Errno
    eNOEXEC         = CInt -> Errno
    Errno (CONST_ENOEXEC)
    eNOLCK :: Errno
    eNOLCK          = CInt -> Errno
    Errno (CONST_ENOLCK)
    eNOLINK :: Errno
    eNOLINK         = CInt -> Errno
    Errno (CONST_ENOLINK)
    eNOMEM :: Errno
    eNOMEM          = CInt -> Errno
    Errno (CONST_ENOMEM)
    eNOMSG :: Errno
    eNOMSG          = CInt -> Errno
    Errno (CONST_ENOMSG)
    eNONET :: Errno
    eNONET          = CInt -> Errno
    Errno (CONST_ENONET)
    eNOPROTOOPT :: Errno
    eNOPROTOOPT     = CInt -> Errno
    Errno (CONST_ENOPROTOOPT)
    eNOSPC :: Errno
    eNOSPC          = CInt -> Errno
    Errno (CONST_ENOSPC)
    eNOSR :: Errno
    eNOSR           = CInt -> Errno
    Errno (CONST_ENOSR)
    eNOSTR :: Errno
    eNOSTR          = CInt -> Errno
    Errno (CONST_ENOSTR)
    eNOSYS :: Errno
    eNOSYS          = CInt -> Errno
    Errno (CONST_ENOSYS)
    eNOTBLK :: Errno
    eNOTBLK         = CInt -> Errno
    Errno (CONST_ENOTBLK)
    eNOTCONN :: Errno
    eNOTCONN        = CInt -> Errno
    Errno (CONST_ENOTCONN)
    eNOTDIR :: Errno
    eNOTDIR         = CInt -> Errno
    Errno (CONST_ENOTDIR)
    eNOTEMPTY :: Errno
    eNOTEMPTY       = CInt -> Errno
    Errno (CONST_ENOTEMPTY)
    eNOTSOCK :: Errno
    eNOTSOCK        = CInt -> Errno
    Errno (CONST_ENOTSOCK)
    eNOTSUP :: Errno
    eNOTSUP         = CInt -> Errno
    Errno (CONST_ENOTSUP)
    -- ^ @since 4.7.0.0
    eNOTTY :: Errno
    eNOTTY          = CInt -> Errno
    Errno (CONST_ENOTTY)
    eNXIO :: Errno
    eNXIO           = CInt -> Errno
    Errno (CONST_ENXIO)
    eOPNOTSUPP :: Errno
    eOPNOTSUPP      = CInt -> Errno
    Errno (CONST_EOPNOTSUPP)
    ePERM :: Errno
    ePERM           = CInt -> Errno
    Errno (CONST_EPERM)
    ePFNOSUPPORT :: Errno
    ePFNOSUPPORT    = CInt -> Errno
    Errno (CONST_EPFNOSUPPORT)
    ePIPE :: Errno
    ePIPE           = CInt -> Errno
    Errno (CONST_EPIPE)
    ePROCLIM :: Errno
    ePROCLIM        = CInt -> Errno
    Errno (CONST_EPROCLIM)
    ePROCUNAVAIL :: Errno
    ePROCUNAVAIL    = CInt -> Errno
    Errno (CONST_EPROCUNAVAIL)
    ePROGMISMATCH :: Errno
    ePROGMISMATCH   = CInt -> Errno
    Errno (CONST_EPROGMISMATCH)
    ePROGUNAVAIL :: Errno
    ePROGUNAVAIL    = CInt -> Errno
    Errno (CONST_EPROGUNAVAIL)
    ePROTO :: Errno
    ePROTO          = CInt -> Errno
    Errno (CONST_EPROTO)
    ePROTONOSUPPORT :: Errno
    ePROTONOSUPPORT = CInt -> Errno
    Errno (CONST_EPROTONOSUPPORT)
    ePROTOTYPE :: Errno
    ePROTOTYPE      = CInt -> Errno
    Errno (CONST_EPROTOTYPE)
    eRANGE :: Errno
    eRANGE          = CInt -> Errno
    Errno (CONST_ERANGE)
    eREMCHG :: Errno
    eREMCHG         = CInt -> Errno
    Errno (CONST_EREMCHG)
    eREMOTE :: Errno
    eREMOTE         = CInt -> Errno
    Errno (CONST_EREMOTE)
    eROFS :: Errno
    eROFS           = CInt -> Errno
    Errno (CONST_EROFS)
    eRPCMISMATCH :: Errno
    eRPCMISMATCH    = CInt -> Errno
    Errno (CONST_ERPCMISMATCH)
    eRREMOTE :: Errno
    eRREMOTE        = CInt -> Errno
    Errno (CONST_ERREMOTE)
    eSHUTDOWN :: Errno
    eSHUTDOWN       = CInt -> Errno
    Errno (CONST_ESHUTDOWN)
    eSOCKTNOSUPPORT :: Errno
    eSOCKTNOSUPPORT = CInt -> Errno
    Errno (CONST_ESOCKTNOSUPPORT)
    eSPIPE :: Errno
    eSPIPE          = CInt -> Errno
    Errno (CONST_ESPIPE)
    eSRCH :: Errno
    eSRCH           = CInt -> Errno
    Errno (CONST_ESRCH)
    eSRMNT :: Errno
    eSRMNT          = CInt -> Errno
    Errno (CONST_ESRMNT)
    eSTALE :: Errno
    eSTALE          = CInt -> Errno
    Errno (CONST_ESTALE)
    eTIME :: Errno
    eTIME           = CInt -> Errno
    Errno (CONST_ETIME)
    eTIMEDOUT :: Errno
    eTIMEDOUT       = CInt -> Errno
    Errno (CONST_ETIMEDOUT)
    eTOOMANYREFS :: Errno
    eTOOMANYREFS    = CInt -> Errno
    Errno (CONST_ETOOMANYREFS)
    eTXTBSY :: Errno
    eTXTBSY         = CInt -> Errno
    Errno (CONST_ETXTBSY)
    eUSERS :: Errno
    eUSERS          = CInt -> Errno
    Errno (CONST_EUSERS)
    eWOULDBLOCK :: Errno
    eWOULDBLOCK     = CInt -> Errno
    Errno (CONST_EWOULDBLOCK)
    eXDEV :: Errno
    eXDEV           = CInt -> Errno
    Errno (CONST_EXDEV)

    -- | Yield 'True' if the given 'Errno' value is valid on the system.
    -- This implies that the 'Eq' instance of 'Errno' is also system dependent
    -- as it is only defined for valid values of 'Errno'.
    --
    isValidErrno               :: Errno -> Bool
    --
    -- the configure script sets all invalid "errno"s to -1
    --
    isValidErrno :: Errno -> Bool
    isValidErrno (Errno CInt
    errno)  = CInt
    errno CInt -> CInt -> Bool
    forall a. Eq a => a -> a -> Bool
    /= -CInt
    1

    -- access to the current thread's "errno" value
    -- --------------------------------------------

    -- | Get the current value of @errno@ in the current thread.
    --
    -- On GHC, the runtime will ensure that any Haskell thread will only see "its own"
    -- @errno@, by saving and restoring the value when Haskell threads are scheduled
    -- across OS threads.
    getErrno :: IO Errno

    -- We must call a C function to get the value of errno in general.  On
    -- threaded systems, errno is hidden behind a C macro so that each OS
    -- thread gets its own copy (`saved_errno`, which `rts/Schedule.c` restores
    -- back into the thread-local `errno` when a Haskell thread is rescheduled).
    getErrno :: IO Errno
    getErrno = do CInt
    e <- IO CInt
    get_errno; Errno -> IO Errno
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (CInt -> Errno
    Errno CInt
    e)
    foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO CInt

    -- | Reset the current thread\'s @errno@ value to 'eOK'.
    --
    resetErrno :: IO ()

    -- Again, setting errno has to be done via a C function.
    resetErrno :: IO ()
    resetErrno = CInt -> IO ()
    set_errno CInt
    0
    foreign import ccall unsafe "HsBase.h __hscore_set_errno" set_errno :: CInt -> IO ()

    -- throw current "errno" value
    -- ---------------------------

    -- | Throw an 'IOError' corresponding to the current value of 'getErrno'.
    --
    throwErrno     :: String        -- ^ textual description of the error location
                   -> IO a
    throwErrno :: forall a. String -> IO a
    throwErrno String
    loc  =
      do
        Errno
    errno <- IO Errno
    getErrno
        IOError -> IO a
    forall a. IOError -> IO a
    ioError (String -> Errno -> Maybe Handle -> Maybe String -> IOError
    errnoToIOError String
    loc Errno
    errno Maybe Handle
    forall a. Maybe a
    Nothing Maybe String
    forall a. Maybe a
    Nothing)

    -- guards for IO operations that may fail
    -- --------------------------------------

    -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
    -- if the result value of the 'IO' action meets the given predicate.
    --
    throwErrnoIf    :: (a -> Bool)  -- ^ predicate to apply to the result value
                                    -- of the 'IO' operation
                    -> String       -- ^ textual description of the location
                    -> IO a         -- ^ the 'IO' operation to be executed
                    -> IO a
    throwErrnoIf :: forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIf a -> Bool
    pred String
    loc IO a
    f  =
      do
        a
    res <- IO a
    f
        if a -> Bool
    pred a
    res then String -> IO a
    forall a. String -> IO a
    throwErrno String
    loc else a -> IO a
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    res

    -- | as 'throwErrnoIf', but discards the result of the 'IO' action after
    -- error handling.
    --
    throwErrnoIf_   :: (a -> Bool) -> String -> IO a -> IO ()
    throwErrnoIf_ :: forall a. (a -> Bool) -> String -> IO a -> IO ()
    throwErrnoIf_ a -> Bool
    pred String
    loc IO a
    f  = IO a -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO a -> IO ()) -> IO a -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (a -> Bool) -> String -> IO a -> IO a
    forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIf a -> Bool
    pred String
    loc IO a
    f

    -- | as 'throwErrnoIf', but retry the 'IO' action when it yields the
    -- error code 'eINTR' - this amounts to the standard retry loop for
    -- interrupted POSIX system calls.
    --
    throwErrnoIfRetry            :: (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIfRetry :: forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIfRetry a -> Bool
    pred String
    loc IO a
    f  =
      do
        a
    res <- IO a
    f
        if a -> Bool
    pred a
    res
          then do
            Errno
    err <- IO Errno
    getErrno
            if Errno
    err Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eINTR
              then (a -> Bool) -> String -> IO a -> IO a
    forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIfRetry a -> Bool
    pred String
    loc IO a
    f
              else String -> IO a
    forall a. String -> IO a
    throwErrno String
    loc
          else a -> IO a
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    res

    -- | as 'throwErrnoIfRetry', but additionally if the operation
    -- yields the error code 'eAGAIN' or 'eWOULDBLOCK', an alternative
    -- action is executed before retrying.
    --
    throwErrnoIfRetryMayBlock
                    :: (a -> Bool)  -- ^ predicate to apply to the result value
                                    -- of the 'IO' operation
                    -> String       -- ^ textual description of the location
                    -> IO a         -- ^ the 'IO' operation to be executed
                    -> IO b         -- ^ action to execute before retrying if
                                    -- an immediate retry would block
                    -> IO a
    throwErrnoIfRetryMayBlock :: forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
    throwErrnoIfRetryMayBlock a -> Bool
    pred String
    loc IO a
    f IO b
    on_block  =
      do
        a
    res <- IO a
    f
        if a -> Bool
    pred a
    res
          then do
            Errno
    err <- IO Errno
    getErrno
            if Errno
    err Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eINTR
              then (a -> Bool) -> String -> IO a -> IO b -> IO a
    forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
    throwErrnoIfRetryMayBlock a -> Bool
    pred String
    loc IO a
    f IO b
    on_block
              else if Errno
    err Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eWOULDBLOCK Bool -> Bool -> Bool
    || Errno
    err Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eAGAIN
                     then do b
    _ <- IO b
    on_block
                             (a -> Bool) -> String -> IO a -> IO b -> IO a
    forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
    throwErrnoIfRetryMayBlock a -> Bool
    pred String
    loc IO a
    f IO b
    on_block
                     else String -> IO a
    forall a. String -> IO a
    throwErrno String
    loc
          else a -> IO a
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    res

    -- | as 'throwErrnoIfRetry', but discards the result.
    --
    throwErrnoIfRetry_            :: (a -> Bool) -> String -> IO a -> IO ()
    throwErrnoIfRetry_ :: forall a. (a -> Bool) -> String -> IO a -> IO ()
    throwErrnoIfRetry_ a -> Bool
    pred String
    loc IO a
    f  = IO a -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO a -> IO ()) -> IO a -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (a -> Bool) -> String -> IO a -> IO a
    forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIfRetry a -> Bool
    pred String
    loc IO a
    f

    -- | as 'throwErrnoIfRetryMayBlock', but discards the result.
    --
    throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO ()
    throwErrnoIfRetryMayBlock_ :: forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO ()
    throwErrnoIfRetryMayBlock_ a -> Bool
    pred String
    loc IO a
    f IO b
    on_block
      = IO a -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO a -> IO ()) -> IO a -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (a -> Bool) -> String -> IO a -> IO b -> IO a
    forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
    throwErrnoIfRetryMayBlock a -> Bool
    pred String
    loc IO a
    f IO b
    on_block

    -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
    -- if the 'IO' action returns a result of @-1@.
    --
    throwErrnoIfMinus1 :: (Eq a, Num a) => String -> IO a -> IO a
    throwErrnoIfMinus1 :: forall a. (Eq a, Num a) => String -> IO a -> IO a
    throwErrnoIfMinus1  = (a -> Bool) -> String -> IO a -> IO a
    forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIf (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- | as 'throwErrnoIfMinus1', but discards the result.
    --
    throwErrnoIfMinus1_ :: (Eq a, Num a) => String -> IO a -> IO ()
    throwErrnoIfMinus1_ :: forall a. (Eq a, Num a) => String -> IO a -> IO ()
    throwErrnoIfMinus1_  = (a -> Bool) -> String -> IO a -> IO ()
    forall a. (a -> Bool) -> String -> IO a -> IO ()
    throwErrnoIf_ (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
    -- if the 'IO' action returns a result of @-1@, but retries in case of
    -- an interrupted operation.
    --
    throwErrnoIfMinus1Retry :: (Eq a, Num a) => String -> IO a -> IO a
    throwErrnoIfMinus1Retry :: forall a. (Eq a, Num a) => String -> IO a -> IO a
    throwErrnoIfMinus1Retry  = (a -> Bool) -> String -> IO a -> IO a
    forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIfRetry (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- | as 'throwErrnoIfMinus1', but discards the result.
    --
    throwErrnoIfMinus1Retry_ :: (Eq a, Num a) => String -> IO a -> IO ()
    throwErrnoIfMinus1Retry_ :: forall a. (Eq a, Num a) => String -> IO a -> IO ()
    throwErrnoIfMinus1Retry_  = (a -> Bool) -> String -> IO a -> IO ()
    forall a. (a -> Bool) -> String -> IO a -> IO ()
    throwErrnoIfRetry_ (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- | as 'throwErrnoIfMinus1Retry', but checks for operations that would block.
    --
    throwErrnoIfMinus1RetryMayBlock :: (Eq a, Num a)
                                    => String -> IO a -> IO b -> IO a
    throwErrnoIfMinus1RetryMayBlock :: forall a b. (Eq a, Num a) => String -> IO a -> IO b -> IO a
    throwErrnoIfMinus1RetryMayBlock  = (a -> Bool) -> String -> IO a -> IO b -> IO a
    forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
    throwErrnoIfRetryMayBlock (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- | as 'throwErrnoIfMinus1RetryMayBlock', but discards the result.
    --
    throwErrnoIfMinus1RetryMayBlock_ :: (Eq a, Num a)
                                     => String -> IO a -> IO b -> IO ()
    throwErrnoIfMinus1RetryMayBlock_ :: forall a b. (Eq a, Num a) => String -> IO a -> IO b -> IO ()
    throwErrnoIfMinus1RetryMayBlock_  = (a -> Bool) -> String -> IO a -> IO b -> IO ()
    forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO ()
    throwErrnoIfRetryMayBlock_ (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
    -- if the 'IO' action returns 'nullPtr'.
    --
    throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
    throwErrnoIfNull :: forall a. String -> IO (Ptr a) -> IO (Ptr a)
    throwErrnoIfNull  = (Ptr a -> Bool) -> String -> IO (Ptr a) -> IO (Ptr a)
    forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIf (Ptr a -> Ptr a -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ptr a
    forall a. Ptr a
    nullPtr)

    -- | Throw an 'IOError' corresponding to the current value of 'getErrno'
    -- if the 'IO' action returns 'nullPtr',
    -- but retry in case of an interrupted operation.
    --
    throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
    throwErrnoIfNullRetry :: forall a. String -> IO (Ptr a) -> IO (Ptr a)
    throwErrnoIfNullRetry  = (Ptr a -> Bool) -> String -> IO (Ptr a) -> IO (Ptr a)
    forall a. (a -> Bool) -> String -> IO a -> IO a
    throwErrnoIfRetry (Ptr a -> Ptr a -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ptr a
    forall a. Ptr a
    nullPtr)

    -- | as 'throwErrnoIfNullRetry', but checks for operations that would block.
    --
    throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)
    throwErrnoIfNullRetryMayBlock :: forall a b. String -> IO (Ptr a) -> IO b -> IO (Ptr a)
    throwErrnoIfNullRetryMayBlock  = (Ptr a -> Bool) -> String -> IO (Ptr a) -> IO b -> IO (Ptr a)
    forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
    throwErrnoIfRetryMayBlock (Ptr a -> Ptr a -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ptr a
    forall a. Ptr a
    nullPtr)

    -- | as 'throwErrno', but exceptions include the given path when appropriate.
    --
    throwErrnoPath :: String -> FilePath -> IO a
    throwErrnoPath :: forall a. String -> String -> IO a
    throwErrnoPath String
    loc String
    path =
      do
        Errno
    errno <- IO Errno
    getErrno
        IOError -> IO a
    forall a. IOError -> IO a
    ioError (String -> Errno -> Maybe Handle -> Maybe String -> IOError
    errnoToIOError String
    loc Errno
    errno Maybe Handle
    forall a. Maybe a
    Nothing (String -> Maybe String
    forall a. a -> Maybe a
    Just String
    path))

    -- | as 'throwErrnoIf', but exceptions include the given path when
    --   appropriate.
    --
    throwErrnoPathIf :: (a -> Bool) -> String -> FilePath -> IO a -> IO a
    throwErrnoPathIf :: forall a. (a -> Bool) -> String -> String -> IO a -> IO a
    throwErrnoPathIf a -> Bool
    pred String
    loc String
    path IO a
    f =
      do
        a
    res <- IO a
    f
        if a -> Bool
    pred a
    res then String -> String -> IO a
    forall a. String -> String -> IO a
    throwErrnoPath String
    loc String
    path else a -> IO a
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    res

    -- | as 'throwErrnoIf_', but exceptions include the given path when
    --   appropriate.
    --
    throwErrnoPathIf_ :: (a -> Bool) -> String -> FilePath -> IO a -> IO ()
    throwErrnoPathIf_ :: forall a. (a -> Bool) -> String -> String -> IO a -> IO ()
    throwErrnoPathIf_ a -> Bool
    pred String
    loc String
    path IO a
    f  = IO a -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO a -> IO ()) -> IO a -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (a -> Bool) -> String -> String -> IO a -> IO a
    forall a. (a -> Bool) -> String -> String -> IO a -> IO a
    throwErrnoPathIf a -> Bool
    pred String
    loc String
    path IO a
    f

    -- | as 'throwErrnoIfNull', but exceptions include the given path when
    --   appropriate.
    --
    throwErrnoPathIfNull :: String -> FilePath -> IO (Ptr a) -> IO (Ptr a)
    throwErrnoPathIfNull :: forall a. String -> String -> IO (Ptr a) -> IO (Ptr a)
    throwErrnoPathIfNull  = (Ptr a -> Bool) -> String -> String -> IO (Ptr a) -> IO (Ptr a)
    forall a. (a -> Bool) -> String -> String -> IO a -> IO a
    throwErrnoPathIf (Ptr a -> Ptr a -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ptr a
    forall a. Ptr a
    nullPtr)

    -- | as 'throwErrnoIfMinus1', but exceptions include the given path when
    --   appropriate.
    --
    throwErrnoPathIfMinus1 :: (Eq a, Num a) => String -> FilePath -> IO a -> IO a
    throwErrnoPathIfMinus1 :: forall a. (Eq a, Num a) => String -> String -> IO a -> IO a
    throwErrnoPathIfMinus1 = (a -> Bool) -> String -> String -> IO a -> IO a
    forall a. (a -> Bool) -> String -> String -> IO a -> IO a
    throwErrnoPathIf (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- | as 'throwErrnoIfMinus1_', but exceptions include the given path when
    --   appropriate.
    --
    throwErrnoPathIfMinus1_ :: (Eq a, Num a) => String -> FilePath -> IO a -> IO ()
    throwErrnoPathIfMinus1_ :: forall a. (Eq a, Num a) => String -> String -> IO a -> IO ()
    throwErrnoPathIfMinus1_  = (a -> Bool) -> String -> String -> IO a -> IO ()
    forall a. (a -> Bool) -> String -> String -> IO a -> IO ()
    throwErrnoPathIf_ (a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == -a
    1)

    -- conversion of an "errno" value into IO error
    -- --------------------------------------------

    -- | Construct an 'IOError' based on the given 'Errno' value.
    -- The optional information can be used to improve the accuracy of
    -- error messages.
    --
    errnoToIOError  :: String       -- ^ the location where the error occurred
                    -> Errno        -- ^ the error number
                    -> Maybe Handle -- ^ optional handle associated with the error
                    -> Maybe String -- ^ optional filename associated with the error
                    -> IOError
    errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
    errnoToIOError String
    loc Errno
    errno Maybe Handle
    maybeHdl Maybe String
    maybeName = IO IOError -> IOError
    forall a. IO a -> a
    unsafePerformIO (IO IOError -> IOError) -> IO IOError -> IOError
    forall a b. (a -> b) -> a -> b
    $ do
        String
    str <- Errno -> IO (Ptr CChar)
    strerror Errno
    errno IO (Ptr CChar) -> (Ptr CChar -> IO String) -> IO String
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Ptr CChar -> IO String
    peekCString
        IOError -> IO IOError
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Handle
    -> IOErrorType
    -> String
    -> String
    -> Maybe CInt
    -> Maybe String
    -> IOError
    IOError Maybe Handle
    maybeHdl IOErrorType
    errType String
    loc String
    str (CInt -> Maybe CInt
    forall a. a -> Maybe a
    Just CInt
    errno') Maybe String
    maybeName)
        where
        Errno CInt
    errno' = Errno
    errno
        errType :: IOErrorType
    errType
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eOK             = IOErrorType
    OtherError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    e2BIG           = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eACCES          = IOErrorType
    PermissionDenied
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eADDRINUSE      = IOErrorType
    ResourceBusy
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eADDRNOTAVAIL   = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eADV            = IOErrorType
    OtherError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eAFNOSUPPORT    = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eAGAIN          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eALREADY        = IOErrorType
    AlreadyExists
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eBADF           = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eBADMSG         = IOErrorType
    InappropriateType
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eBADRPC         = IOErrorType
    OtherError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eBUSY           = IOErrorType
    ResourceBusy
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eCHILD          = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eCOMM           = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eCONNABORTED    = IOErrorType
    OtherError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eCONNREFUSED    = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eCONNRESET      = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eDEADLK         = IOErrorType
    ResourceBusy
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eDESTADDRREQ    = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eDIRTY          = IOErrorType
    UnsatisfiedConstraints
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eDOM            = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eDQUOT          = IOErrorType
    PermissionDenied
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eEXIST          = IOErrorType
    AlreadyExists
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eFAULT          = IOErrorType
    OtherError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eFBIG           = IOErrorType
    PermissionDenied
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eFTYPE          = IOErrorType
    InappropriateType
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eHOSTDOWN       = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eHOSTUNREACH    = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eIDRM           = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eILSEQ          = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eINPROGRESS     = IOErrorType
    AlreadyExists
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eINTR           = IOErrorType
    Interrupted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eINVAL          = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eIO             = IOErrorType
    HardwareFault
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eISCONN         = IOErrorType
    AlreadyExists
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eISDIR          = IOErrorType
    InappropriateType
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eLOOP           = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eMFILE          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eMLINK          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eMSGSIZE        = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eMULTIHOP       = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNAMETOOLONG    = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNETDOWN        = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNETRESET       = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNETUNREACH     = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNFILE          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOBUFS         = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNODATA         = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNODEV          = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOENT          = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOEXEC         = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOLCK          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOLINK         = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOMEM          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOMSG          = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNONET          = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOPROTOOPT     = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOSPC          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOSR           = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOSTR          = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOSYS          = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOTBLK         = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOTCONN        = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOTDIR         = IOErrorType
    InappropriateType
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOTEMPTY       = IOErrorType
    UnsatisfiedConstraints
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOTSOCK        = IOErrorType
    InvalidArgument
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNOTTY          = IOErrorType
    IllegalOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eNXIO           = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eOPNOTSUPP      = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePERM           = IOErrorType
    PermissionDenied
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePFNOSUPPORT    = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePIPE           = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePROCLIM        = IOErrorType
    PermissionDenied
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePROCUNAVAIL    = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePROGMISMATCH   = IOErrorType
    ProtocolError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePROGUNAVAIL    = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePROTO          = IOErrorType
    ProtocolError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePROTONOSUPPORT = IOErrorType
    ProtocolError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePROTOTYPE      = IOErrorType
    ProtocolError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eRANGE          = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eREMCHG         = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eREMOTE         = IOErrorType
    IllegalOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eROFS           = IOErrorType
    PermissionDenied
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eRPCMISMATCH    = IOErrorType
    ProtocolError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eRREMOTE        = IOErrorType
    IllegalOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eSHUTDOWN       = IOErrorType
    IllegalOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eSOCKTNOSUPPORT = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eSPIPE          = IOErrorType
    UnsupportedOperation
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eSRCH           = IOErrorType
    NoSuchThing
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eSRMNT          = IOErrorType
    UnsatisfiedConstraints
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eSTALE          = IOErrorType
    ResourceVanished
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eTIME           = IOErrorType
    TimeExpired
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eTIMEDOUT       = IOErrorType
    TimeExpired
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eTOOMANYREFS    = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eTXTBSY         = IOErrorType
    ResourceBusy
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eUSERS          = IOErrorType
    ResourceExhausted
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eWOULDBLOCK     = IOErrorType
    OtherError
            | Errno
    errno Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    eXDEV           = IOErrorType
    UnsupportedOperation
            | Bool
    otherwise                = IOErrorType
    OtherError

    foreign import ccall unsafe "string.h" strerror :: Errno -> IO (Ptr CChar)