snap-server-1.1.2.1: src/System/SendFile/Linux.hsc
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ForeignFunctionInterface #-}
------------------------------------------------------------------------------
-- | Linux system-dependent code for 'sendfile'.
module System.SendFile.Linux
( sendFile
, sendFileImpl
, sendFileMode
) where
------------------------------------------------------------------------------
import Control.Concurrent (threadWaitWrite)
import Data.Int (Int64)
import Data.Word (Word64)
import Foreign.C.Error (throwErrnoIfMinus1RetryMayBlock)
#if __GLASGOW_HASKELL__ >= 703
import Foreign.C.Types (CInt (..), CSize (..))
#else
import Foreign.C.Types (CSize)
#endif
import Foreign.Marshal (alloca)
import Foreign.Ptr (Ptr, nullPtr)
import Foreign.Storable (poke)
#if __GLASGOW_HASKELL__ >= 703
import System.Posix.Types (COff (..), CSsize (..), Fd (..))
#else
import System.Posix.Types (COff, CSsize, Fd)
#endif
------------------------------------------------------------------------------
sendFile :: Fd -> Fd -> Word64 -> Word64 -> IO Int64
sendFile = sendFileImpl c_sendfile threadWaitWrite
{-# INLINE sendFile #-}
------------------------------------------------------------------------------
sendFileImpl :: (Fd -> Fd -> Ptr COff -> CSize -> IO CSsize)
-> (Fd -> IO ())
-> Fd -> Fd -> Word64 -> Word64 -> IO Int64
sendFileImpl !raw_sendfile !wait out_fd in_fd off count
| count <= 0 = return 0
| off == 0 = do
nsent <- sendfile raw_sendfile wait out_fd in_fd nullPtr bytes
return $! fromIntegral nsent
| otherwise = alloca $ \poff -> do
poke poff (fromIntegral off)
nsent <- sendfile raw_sendfile wait out_fd in_fd poff bytes
return $! fromIntegral nsent
where
bytes = fromIntegral count
{-# INLINE sendFileImpl #-}
------------------------------------------------------------------------------
sendfile :: (Fd -> Fd -> Ptr COff -> CSize -> IO CSsize)
-> (Fd -> IO ())
-> Fd -> Fd -> Ptr COff -> CSize -> IO CSsize
sendfile raw_sendfile wait out_fd in_fd poff bytes =
throwErrnoIfMinus1RetryMayBlock
"sendfile"
(raw_sendfile out_fd in_fd poff bytes)
(wait out_fd)
{-# INLINE sendfile #-}
------------------------------------------------------------------------------
-- sendfile64 gives LFS support
foreign import ccall unsafe "sys/sendfile.h sendfile64" c_sendfile
:: Fd -> Fd -> Ptr COff -> CSize -> IO CSsize
------------------------------------------------------------------------------
sendFileMode :: String
sendFileMode = "LINUX_SENDFILE"