{-# 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 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 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; 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
    forall a. IOError -> IO a
ioError (String -> Errno -> Maybe Handle -> Maybe String -> IOError
errnoToIOError String
loc Errno
errno forall a. Maybe a
Nothing 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 forall a. String -> IO a
throwErrno String
loc else 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  = forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ 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 forall a. Eq a => a -> a -> Bool
== Errno
eINTR
          then forall a. (a -> Bool) -> String -> IO a -> IO a
throwErrnoIfRetry a -> Bool
pred String
loc IO a
f
          else forall a. String -> IO a
throwErrno String
loc
      else 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 forall a. Eq a => a -> a -> Bool
== Errno
eINTR
          then 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 forall a. Eq a => a -> a -> Bool
== Errno
eWOULDBLOCK Bool -> Bool -> Bool
|| Errno
err forall a. Eq a => a -> a -> Bool
== Errno
eAGAIN
                 then do b
_ <- IO b
on_block
                         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 forall a. String -> IO a
throwErrno String
loc
      else 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  = forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ 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
  = forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ 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  = forall a. (a -> Bool) -> String -> IO a -> IO a
throwErrnoIf (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_  = forall a. (a -> Bool) -> String -> IO a -> IO ()
throwErrnoIf_ (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  = forall a. (a -> Bool) -> String -> IO a -> IO a
throwErrnoIfRetry (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_  = forall a. (a -> Bool) -> String -> IO a -> IO ()
throwErrnoIfRetry_ (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  = forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
throwErrnoIfRetryMayBlock (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_  = forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO ()
throwErrnoIfRetryMayBlock_ (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  = forall a. (a -> Bool) -> String -> IO a -> IO a
throwErrnoIf (forall a. Eq a => a -> a -> Bool
== 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  = forall a. (a -> Bool) -> String -> IO a -> IO a
throwErrnoIfRetry (forall a. Eq a => a -> a -> Bool
== 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  = forall a b. (a -> Bool) -> String -> IO a -> IO b -> IO a
throwErrnoIfRetryMayBlock (forall a. Eq a => a -> a -> Bool
== 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
    forall a. IOError -> IO a
ioError (String -> Errno -> Maybe Handle -> Maybe String -> IOError
errnoToIOError String
loc Errno
errno forall a. Maybe a
Nothing (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 forall a. String -> String -> IO a
throwErrnoPath String
loc String
path else 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  = forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ 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  = forall a. (a -> Bool) -> String -> String -> IO a -> IO a
throwErrnoPathIf (forall a. Eq a => a -> a -> Bool
== 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 = forall a. (a -> Bool) -> String -> String -> IO a -> IO a
throwErrnoPathIf (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_  = forall a. (a -> Bool) -> String -> String -> IO a -> IO ()
throwErrnoPathIf_ (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 = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    String
str <- Errno -> IO (Ptr CChar)
strerror Errno
errno forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr CChar -> IO String
peekCString
    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 (forall a. a -> Maybe a
Just CInt
errno') Maybe String
maybeName)
    where
    Errno CInt
errno' = Errno
errno
    errType :: IOErrorType
errType
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eOK             = IOErrorType
OtherError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
e2BIG           = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eACCES          = IOErrorType
PermissionDenied
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eADDRINUSE      = IOErrorType
ResourceBusy
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eADDRNOTAVAIL   = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eADV            = IOErrorType
OtherError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eAFNOSUPPORT    = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eAGAIN          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eALREADY        = IOErrorType
AlreadyExists
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eBADF           = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eBADMSG         = IOErrorType
InappropriateType
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eBADRPC         = IOErrorType
OtherError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eBUSY           = IOErrorType
ResourceBusy
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eCHILD          = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eCOMM           = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eCONNABORTED    = IOErrorType
OtherError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eCONNREFUSED    = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eCONNRESET      = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eDEADLK         = IOErrorType
ResourceBusy
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eDESTADDRREQ    = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eDIRTY          = IOErrorType
UnsatisfiedConstraints
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eDOM            = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eDQUOT          = IOErrorType
PermissionDenied
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eEXIST          = IOErrorType
AlreadyExists
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eFAULT          = IOErrorType
OtherError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eFBIG           = IOErrorType
PermissionDenied
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eFTYPE          = IOErrorType
InappropriateType
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eHOSTDOWN       = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eHOSTUNREACH    = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eIDRM           = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eILSEQ          = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eINPROGRESS     = IOErrorType
AlreadyExists
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eINTR           = IOErrorType
Interrupted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eINVAL          = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eIO             = IOErrorType
HardwareFault
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eISCONN         = IOErrorType
AlreadyExists
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eISDIR          = IOErrorType
InappropriateType
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eLOOP           = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eMFILE          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eMLINK          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eMSGSIZE        = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eMULTIHOP       = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNAMETOOLONG    = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNETDOWN        = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNETRESET       = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNETUNREACH     = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNFILE          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOBUFS         = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNODATA         = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNODEV          = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOENT          = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOEXEC         = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOLCK          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOLINK         = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOMEM          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOMSG          = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNONET          = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOPROTOOPT     = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOSPC          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOSR           = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOSTR          = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOSYS          = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOTBLK         = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOTCONN        = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOTDIR         = IOErrorType
InappropriateType
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOTEMPTY       = IOErrorType
UnsatisfiedConstraints
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOTSOCK        = IOErrorType
InvalidArgument
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNOTTY          = IOErrorType
IllegalOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eNXIO           = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eOPNOTSUPP      = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePERM           = IOErrorType
PermissionDenied
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePFNOSUPPORT    = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePIPE           = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePROCLIM        = IOErrorType
PermissionDenied
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePROCUNAVAIL    = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePROGMISMATCH   = IOErrorType
ProtocolError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePROGUNAVAIL    = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePROTO          = IOErrorType
ProtocolError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePROTONOSUPPORT = IOErrorType
ProtocolError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
ePROTOTYPE      = IOErrorType
ProtocolError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eRANGE          = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eREMCHG         = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eREMOTE         = IOErrorType
IllegalOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eROFS           = IOErrorType
PermissionDenied
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eRPCMISMATCH    = IOErrorType
ProtocolError
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eRREMOTE        = IOErrorType
IllegalOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eSHUTDOWN       = IOErrorType
IllegalOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eSOCKTNOSUPPORT = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eSPIPE          = IOErrorType
UnsupportedOperation
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eSRCH           = IOErrorType
NoSuchThing
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eSRMNT          = IOErrorType
UnsatisfiedConstraints
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eSTALE          = IOErrorType
ResourceVanished
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eTIME           = IOErrorType
TimeExpired
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eTIMEDOUT       = IOErrorType
TimeExpired
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eTOOMANYREFS    = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eTXTBSY         = IOErrorType
ResourceBusy
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eUSERS          = IOErrorType
ResourceExhausted
        | Errno
errno forall a. Eq a => a -> a -> Bool
== Errno
eWOULDBLOCK     = IOErrorType
OtherError
        | Errno
errno 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)