{-# LINE 1 "src/System/Posix/IO/ByteString.hsc" #-}
{-
/N.B./, There's a bug when trying to use Cabal-style MIN_VERSION_foo(1,2,3)
macros in combination with hsc2hs. We don't need full hsc2hs support
in this file, but if we use CPP instead we get a strange error on
OSX 10.5.8 about "architecture not supported" (even though the
headers work fine with hsc2hs). It turns out that we don't /need/
to combine Cabal-style macros and hsc2hs\/cpp since we can remove
our dependency on the @unix@ package. But this issue is worth making
a note of.
-}

-- GHC 7.6 changed the semantics of the FFI so that we must have
-- the data constructors in scope in order to import functions using
-- the given types. However, those data constructors[1] are not exported
-- in earlier versions, so having @(..)@ will raise warnings on old
-- systems. However, Cabal-style MIN_VERSION_foo(1,2,3) macros don't
-- play nicely with hsc2hs; and we need hsc2hs in lieu of CPP for
-- OS X. So we disable -Wall rather than trying to CPP this problem
-- away. There doesn't appear to be a -fno-warn-foo for this
-- particular issue.
--
-- [1] CSsize(..), COff(..), CInt(..), CSize(..), CChar(..)

{-# LANGUAGE ForeignFunctionInterface #-}
{-# OPTIONS_GHC -fwarn-tabs #-}
----------------------------------------------------------------
--                                                    2021.10.17
-- |
-- Module      :  System.Posix.IO.ByteString
-- Copyright   :  2010--2022 wren romano
-- License     :  BSD-3-Clause
-- Maintainer  :  wren@cpan.org
-- Stability   :  experimental
-- Portability :  non-portable (POSIX.1, XPG4.2; hsc2hs, FFI)
--
-- Provides a strict-'BS.ByteString' file-descriptor based I\/O
-- API, designed loosely after the @String@ file-descriptor based
-- I\/O API in "System.Posix.IO". The functions here wrap standard
-- C implementations of the functions specified by the ISO\/IEC
-- 9945-1:1990 (``POSIX.1'') and X\/Open Portability Guide Issue
-- 4, Version 2 (``XPG4.2'') specifications.
----------------------------------------------------------------
module System.Posix.IO.ByteString
    (
    -- * I\/O with file descriptors
    -- ** Reading
    -- *** The POSIX.1 @read(2)@ syscall
      fdRead
    , fdReadBuf
    , tryFdReadBuf
    , fdReads
    -- *** The XPG4.2 @readv(2)@ syscall
    -- , fdReadv
    , fdReadvBuf
    , tryFdReadvBuf
    -- *** The XPG4.2 @pread(2)@ syscall
    , fdPread
    , fdPreadBuf
    , tryFdPreadBuf
    , fdPreads

    -- ** Writing
    -- *** The POSIX.1 @write(2)@ syscall
    , fdWrite
    , fdWriteBuf
    , tryFdWriteBuf
    , fdWrites
    -- *** The XPG4.2 @writev(2)@ syscall
    , fdWritev
    , fdWritevBuf
    , tryFdWritevBuf
    -- *** The XPG4.2 @pwrite(2)@ syscall
    , fdPwrite
    , fdPwriteBuf
    , tryFdPwriteBuf

    -- ** Seeking
    -- | These functions are not 'BS.ByteString' related, but are
    -- provided here for API completeness.

    -- *** The POSIX.1 @lseek(2)@ syscall
    , fdSeek
    , tryFdSeek
    ) where

import           Data.Word                (Word8)
import qualified Data.ByteString          as BS
import qualified Data.ByteString.Internal as BSI
import qualified Data.ByteString.Unsafe   as BSU

import           System.IO                (SeekMode(..))
import qualified System.IO.Error          as IOE
import qualified System.Posix.Internals   as Base
import           System.Posix.Types.Iovec
import           System.Posix.Types       ( Fd, ByteCount, FileOffset
                                          , CSsize(..), COff(..))
import           Foreign.C.Types          (CInt(..), CSize(..), CChar(..))

import qualified Foreign.C.Error          as C
import           Foreign.C.Error.Safe
import           Foreign.Ptr              (Ptr, castPtr, plusPtr)
import qualified Foreign.Marshal.Array    as FMA (withArrayLen)

-- For the functor instance of 'Either', aka 'right' for ArrowChoice(->)
import Control.Arrow (ArrowChoice(..))

-- iovec, writev, and readv are in <sys/uio.h>, but we must include
-- <sys/types.h> and <unistd.h> for legacy reasons.




----------------------------------------------------------------
-- | Throw an 'IOE.IOError' for EOF.
ioErrorEOF :: String -> IO a
ioErrorEOF :: forall a. String -> IO a
ioErrorEOF String
fun =
    forall a. IOError -> IO a
IOE.ioError
        (IOError -> String -> IOError
IOE.ioeSetErrorString
            (IOErrorType -> String -> Maybe Handle -> Maybe String -> IOError
IOE.mkIOError IOErrorType
IOE.eofErrorType String
fun forall a. Maybe a
Nothing forall a. Maybe a
Nothing)
            String
"EOF")


----------------------------------------------------------------
foreign import ccall safe "read"
    -- ssize_t read(int fildes, void *buf, size_t nbyte);
    c_safe_read :: CInt -> Ptr CChar -> CSize -> IO CSsize


-- | Read data from an 'Fd' into memory. This is exactly equivalent
-- to the POSIX.1 @read(2)@ system call, except that we return 0
-- bytes read if the @ByteCount@ argument is less than or equal to
-- zero (instead of throwing an errno exception). /N.B./, this
-- behavior is different from the version in @unix-2.4.2.0@ which
-- only checks for equality to zero. If there are any errors, then
-- they are thrown as 'IOE.IOError' exceptions.
--
-- /Since: 0.3.0/
fdReadBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory in which to put the data.
    -> ByteCount    -- ^ How many bytes to try to read.
    -> IO ByteCount -- ^ How many bytes were actually read (zero for EOF).
fdReadBuf :: Fd -> Ptr Word8 -> ByteCount -> IO ByteCount
fdReadBuf Fd
fd Ptr Word8
buf ByteCount
nbytes
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ByteCount
0
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => String -> IO a -> IO a
C.throwErrnoIfMinus1Retry String
_fdReadBuf
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CChar -> ByteCount -> IO CSsize
c_safe_read
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
buf)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)

_fdReadBuf :: String
_fdReadBuf :: String
_fdReadBuf = String
"System.Posix.IO.ByteString.fdReadBuf"
{-# NOINLINE _fdReadBuf #-}


-- | Read data from an 'Fd' into memory. This is a variation of
-- 'fdReadBuf' which returns errors with an 'Either' instead of
-- throwing exceptions.
--
-- /Since: 0.3.3/
tryFdReadBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory in which to put the data.
    -> ByteCount    -- ^ How many bytes to try to read.
    -> IO (Either C.Errno ByteCount)
        -- ^ How many bytes were actually read (zero for EOF).
tryFdReadBuf :: Fd -> Ptr Word8 -> ByteCount -> IO (Either Errno ByteCount)
tryFdReadBuf Fd
fd Ptr Word8
buf ByteCount
nbytes
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right ByteCount
0)
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right forall a b. (Integral a, Num b) => a -> b
fromIntegral)
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => IO a -> IO (Either Errno a)
eitherErrnoIfMinus1Retry
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CChar -> ByteCount -> IO CSsize
c_safe_read
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
buf)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)


----------------------------------------------------------------
-- | Read data from an 'Fd' and convert it to a 'BS.ByteString'.
-- Throws an exception if this is an invalid descriptor, or EOF has
-- been reached. This is essentially equivalent to 'fdReadBuf'; the
-- differences are that we allocate a byte buffer for the @ByteString@,
-- and that we detect EOF and throw an 'IOE.IOError'.
fdRead
    :: Fd
    -> ByteCount        -- ^ How many bytes to try to read.
    -> IO BS.ByteString -- ^ The bytes read.
fdRead :: Fd -> ByteCount -> IO ByteString
fdRead Fd
fd ByteCount
nbytes
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
BS.empty
    | Bool
otherwise   =
        Int -> (Ptr Word8 -> IO Int) -> IO ByteString
BSI.createAndTrim (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes) forall a b. (a -> b) -> a -> b
$ \Ptr Word8
buf -> do
            ByteCount
rc <- Fd -> Ptr Word8 -> ByteCount -> IO ByteCount
fdReadBuf Fd
fd Ptr Word8
buf ByteCount
nbytes
            if ByteCount
0 forall a. Eq a => a -> a -> Bool
== ByteCount
rc
                then forall a. String -> IO a
ioErrorEOF String
_fdRead
                else forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
rc)

_fdRead :: String
_fdRead :: String
_fdRead = String
"System.Posix.IO.ByteString.fdRead"
{-# NOINLINE _fdRead #-}


----------------------------------------------------------------
-- | Read data from an 'Fd' and convert it to a 'BS.ByteString'.
-- Throws an exception if this is an invalid descriptor, or EOF has
-- been reached.
--
-- This version takes a kind of stateful predicate for whether and
-- how long to keep retrying. Assume the function is called as
-- @fdReads f z0 fd n0@. We will attempt to read @n0@ bytes from
-- @fd@. If we fall short, then we will call @f len z@ where @len@
-- is the total number of bytes read so far and @z@ is the current
-- state (initially @z0@). If it returns @Nothing@ then we will
-- give up and return the current buffer; otherwise we will retry
-- with the new state, continuing from where we left off.
--
-- For example, to define a function that tries up to @n@ times,
-- we can use:
--
-- > fdReadUptoNTimes :: Int -> Fd -> ByteCount -> IO ByteString
-- > fdReadUptoNTimes n0 = fdReads retry n0
-- >     where
-- >     retry _ 0 = Nothing
-- >     retry _ n = Just $! n-1
--
-- The benefit of doing this instead of the naive approach of calling
-- 'fdRead' repeatedly is that we only need to allocate one byte
-- buffer, and trim it once at the end--- whereas the naive approach
-- would allocate a buffer, trim it to the number of bytes read,
-- and then concatenate with the previous one (another allocation,
-- plus copying everything over) for each time around the loop.
--
-- /Since: 0.2.1/
fdReads
    :: (ByteCount -> a -> Maybe a) -- ^ A stateful predicate for retrying.
    -> a                           -- ^ An initial state for the predicate.
    -> Fd
    -> ByteCount                   -- ^ How many bytes to try to read.
    -> IO BS.ByteString            -- ^ The bytes read.
fdReads :: forall a.
(ByteCount -> a -> Maybe a)
-> a -> Fd -> ByteCount -> IO ByteString
fdReads ByteCount -> a -> Maybe a
f a
z0 Fd
fd ByteCount
n0
    | ByteCount
n0 forall a. Ord a => a -> a -> Bool
<= ByteCount
0   = forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
BS.empty
    | Bool
otherwise = Int -> (Ptr Word8 -> IO Int) -> IO ByteString
BSI.createAndTrim (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
n0) (forall {b}.
Num b =>
a -> ByteCount -> ByteCount -> Ptr Word8 -> IO b
go a
z0 ByteCount
0 ByteCount
n0)
    where
    go :: a -> ByteCount -> ByteCount -> Ptr Word8 -> IO b
go a
_ ByteCount
len ByteCount
n Ptr Word8
buf | ByteCount
len seq :: forall a b. a -> b -> b
`seq` ByteCount
n seq :: forall a b. a -> b -> b
`seq` Ptr Word8
buf seq :: forall a b. a -> b -> b
`seq` Bool
False = forall a. HasCallStack => a
undefined
    go a
z ByteCount
len ByteCount
n Ptr Word8
buf = do
        ByteCount
rc <- Fd -> Ptr Word8 -> ByteCount -> IO ByteCount
fdReadBuf Fd
fd Ptr Word8
buf ByteCount
n
        let len' :: ByteCount
len' = ByteCount
len forall a. Num a => a -> a -> a
+ ByteCount
rc
        case ByteCount
rc of
          ByteCount
_ | ByteCount
rc forall a. Eq a => a -> a -> Bool
== ByteCount
0 -> forall a. String -> IO a
ioErrorEOF String
_fdReads
            | ByteCount
rc forall a. Eq a => a -> a -> Bool
== ByteCount
n -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
len') -- Finished.
            | Bool
otherwise ->
                case ByteCount -> a -> Maybe a
f ByteCount
len' a
z of
                Maybe a
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
len') -- Gave up.
                Just a
z' ->
                    a -> ByteCount -> ByteCount -> Ptr Word8 -> IO b
go a
z' ByteCount
len' (ByteCount
n forall a. Num a => a -> a -> a
- ByteCount
rc) (Ptr Word8
buf forall a b. Ptr a -> Int -> Ptr b
`plusPtr` forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
rc)

_fdReads :: String
_fdReads :: String
_fdReads = String
"System.Posix.IO.ByteString.fdReads"
{-# NOINLINE _fdReads #-}


----------------------------------------------------------------
foreign import ccall safe "readv"
    -- ssize_t readv(int fildes, const struct iovec *iov, int iovcnt);
    c_safe_readv :: CInt -> Ptr CIovec -> CInt -> IO CSsize
{-
-- N.B., c_safe_readv will throw errno=EINVAL
-- if iovcnt <= 0 || > 16,
-- if one of the iov_len values in the iov array was negative,
-- if the sum of the iov_len values in the iov array overflowed a 32-bit integer.

fdReadvBufSafe :: Fd -> Ptr CIovec -> Int -> IO ByteCount
fdReadvBufSafe fd = go 0
    where
    go rc bufs len
        | len <= 0  = return rc
        | otherwise = do
            m <- checkIovecs bufs (min 16 len)
            case m of
                Nothing                 -> error
                Just (bufs', l, nbytes) -> do
                    rc' <- fdReadvBuf fd bufs l
                    if rc' == nbytes
                        then go (rc+rc') bufs' (len-l)
                        else return (rc+rc')

checkIovecs :: Ptr CIovec -> Int -> IO (Maybe (Ptr CIovec, Int, ByteCount))
checkIovecs = go (0 :: Int32) 0
    where
    go nbytes n p len
        | nbytes `seq` n `seq` p `seq` len `seq` False = undefined
        | len == 0  = return (Just (p, n, fromIntegral nbytes)
        | otherwise = do
            l <- iov_len <$> peek p
            if l < 0
                then return Nothing
                else do
                    let nbytes' = nbytes+l
                    if nbytes' < 0
                        then return (Just (p, n, fromIntegral nbytes)
                        else go nbytes' (n+1) (p++) (len-1)
-}


-- | Read data from an 'Fd' and scatter it into memory. This is
-- exactly equivalent to the XPG4.2 @readv(2)@ system call, except
-- that we return 0 bytes read if the @Int@ argument is less than
-- or equal to zero (instead of throwing an 'C.eINVAL' exception).
-- If there are any errors, then they are thrown as 'IOE.IOError'
-- exceptions.
--
-- TODO: better documentation.
--
-- /Since: 0.3.0/
fdReadvBuf
    :: Fd
    -> Ptr CIovec   -- ^ A C-style array of buffers to fill.
    -> Int          -- ^ How many buffers there are.
    -> IO ByteCount -- ^ How many bytes were actually read (zero for EOF).
fdReadvBuf :: Fd -> Ptr CIovec -> Int -> IO ByteCount
fdReadvBuf Fd
fd Ptr CIovec
bufs Int
len
    | Int
len forall a. Ord a => a -> a -> Bool
<= Int
0  = forall (m :: * -> *) a. Monad m => a -> m a
return ByteCount
0
    | Bool
otherwise =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => String -> IO a -> IO a
C.throwErrnoIfMinus1Retry String
_fdReadvBuf
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CIovec -> CInt -> IO CSsize
c_safe_readv (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd) Ptr CIovec
bufs (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)

_fdReadvBuf :: String
_fdReadvBuf :: String
_fdReadvBuf = String
"System.Posix.IO.ByteString.fdReadvBuf"
{-# NOINLINE _fdReadvBuf #-}


-- | Read data from an 'Fd' and scatter it into memory. This is a
-- variation of 'fdReadvBuf' which returns errors with an 'Either'
-- instead of throwing exceptions.
--
-- /Since: 0.3.3/
tryFdReadvBuf
    :: Fd
    -> Ptr CIovec   -- ^ A C-style array of buffers to fill.
    -> Int          -- ^ How many buffers there are.
    -> IO (Either C.Errno ByteCount)
        -- ^ How many bytes were actually read (zero for EOF).
tryFdReadvBuf :: Fd -> Ptr CIovec -> Int -> IO (Either Errno ByteCount)
tryFdReadvBuf Fd
fd Ptr CIovec
bufs Int
len
    | Int
len forall a. Ord a => a -> a -> Bool
<= Int
0  = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right ByteCount
0)
    | Bool
otherwise =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right forall a b. (Integral a, Num b) => a -> b
fromIntegral)
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => IO a -> IO (Either Errno a)
eitherErrnoIfMinus1Retry
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CIovec -> CInt -> IO CSsize
c_safe_readv (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd) Ptr CIovec
bufs (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)


-- TODO: What's a reasonable wrapper for fdReadvBuf to make it Haskellish?

----------------------------------------------------------------
foreign import ccall safe "pread"
    -- ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
    c_safe_pread :: CInt -> Ptr Word8 -> CSize -> COff -> IO CSsize


-- | Read data from a specified position in the 'Fd' into memory,
-- without altering the position stored in the @Fd@. This is exactly
-- equivalent to the XPG4.2 @pread(2)@ system call, except that we
-- return 0 bytes read if the @Int@ argument is less than or equal
-- to zero (instead of throwing an errno exception). If there are
-- any errors, then they are thrown as 'IOE.IOError' exceptions.
--
-- /Since: 0.3.0/
fdPreadBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory in which to put the data.
    -> ByteCount    -- ^ How many bytes to try to read.
    -> FileOffset   -- ^ Where to read the data from.
    -> IO ByteCount -- ^ How many bytes were actually read (zero for EOF).
fdPreadBuf :: Fd -> Ptr Word8 -> ByteCount -> COff -> IO ByteCount
fdPreadBuf Fd
fd Ptr Word8
buf ByteCount
nbytes COff
offset
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ByteCount
0
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => String -> IO a -> IO a
C.throwErrnoIfMinus1Retry String
_fdPreadBuf
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr Word8 -> ByteCount -> COff -> IO CSsize
c_safe_pread
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    Ptr Word8
buf
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral COff
offset)

_fdPreadBuf :: String
_fdPreadBuf :: String
_fdPreadBuf = String
"System.Posix.IO.ByteString.fdPreadBuf"
{-# NOINLINE _fdPreadBuf #-}


-- | Read data from a specified position in the 'Fd' into memory,
-- without altering the position stored in the @Fd@. This is a
-- variation of 'fdPreadBuf' which returns errors with an 'Either'
-- instead of throwing exceptions.
--
-- /Since: 0.3.3/
tryFdPreadBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory in which to put the data.
    -> ByteCount    -- ^ How many bytes to try to read.
    -> FileOffset   -- ^ Where to read the data from.
    -> IO (Either C.Errno ByteCount)
        -- ^ How many bytes were actually read (zero for EOF).
tryFdPreadBuf :: Fd -> Ptr Word8 -> ByteCount -> COff -> IO (Either Errno ByteCount)
tryFdPreadBuf Fd
fd Ptr Word8
buf ByteCount
nbytes COff
offset
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right ByteCount
0)
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right forall a b. (Integral a, Num b) => a -> b
fromIntegral)
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => IO a -> IO (Either Errno a)
eitherErrnoIfMinus1Retry
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr Word8 -> ByteCount -> COff -> IO CSsize
c_safe_pread
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    Ptr Word8
buf
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral COff
offset)

----------------------------------------------------------------
-- | Read data from a specified position in the 'Fd' and convert
-- it to a 'BS.ByteString', without altering the position stored
-- in the @Fd@. Throws an exception if this is an invalid descriptor,
-- or EOF has been reached. This is essentially equivalent to
-- 'fdPreadBuf'; the differences are that we allocate a byte buffer
-- for the @ByteString@, and that we detect EOF and throw an
-- 'IOE.IOError'.
--
-- /Since: 0.3.0/
fdPread
    :: Fd
    -> ByteCount        -- ^ How many bytes to try to read.
    -> FileOffset       -- ^ Where to read the data from.
    -> IO BS.ByteString -- ^ The bytes read.
fdPread :: Fd -> ByteCount -> COff -> IO ByteString
fdPread Fd
fd ByteCount
nbytes COff
offset
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
BS.empty
    | Bool
otherwise   =
        Int -> (Ptr Word8 -> IO Int) -> IO ByteString
BSI.createAndTrim (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes) forall a b. (a -> b) -> a -> b
$ \Ptr Word8
buf -> do
            ByteCount
rc <- Fd -> Ptr Word8 -> ByteCount -> COff -> IO ByteCount
fdPreadBuf Fd
fd Ptr Word8
buf ByteCount
nbytes COff
offset
            if ByteCount
0 forall a. Eq a => a -> a -> Bool
== ByteCount
rc
                then forall a. String -> IO a
ioErrorEOF String
_fdPread
                else forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
rc)

_fdPread :: String
_fdPread :: String
_fdPread = String
"System.Posix.IO.ByteString.fdPread"
{-# NOINLINE _fdPread #-}

----------------------------------------------------------------
-- | Read data from a specified position in the 'Fd' and convert
-- it to a 'BS.ByteString', without altering the position stored
-- in the @Fd@. Throws an exception if this is an invalid descriptor,
-- or EOF has been reached. This is a 'fdPreadBuf' based version
-- of 'fdReads'; see those functions for more details.
--
-- /Since: 0.3.1/
fdPreads
    :: (ByteCount -> a -> Maybe a) -- ^ A stateful predicate for retrying.
    -> a                           -- ^ An initial state for the predicate.
    -> Fd
    -> ByteCount                   -- ^ How many bytes to try to read.
    -> FileOffset                  -- ^ Where to read the data from.
    -> IO BS.ByteString            -- ^ The bytes read.
fdPreads :: forall a.
(ByteCount -> a -> Maybe a)
-> a -> Fd -> ByteCount -> COff -> IO ByteString
fdPreads ByteCount -> a -> Maybe a
f a
z0 Fd
fd ByteCount
n0 COff
offset
    | ByteCount
n0 forall a. Ord a => a -> a -> Bool
<= ByteCount
0   = forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
BS.empty
    | Bool
otherwise = Int -> (Ptr Word8 -> IO Int) -> IO ByteString
BSI.createAndTrim (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
n0) (forall {b}.
Num b =>
a -> ByteCount -> ByteCount -> Ptr Word8 -> IO b
go a
z0 ByteCount
0 ByteCount
n0)
    where
    go :: a -> ByteCount -> ByteCount -> Ptr Word8 -> IO b
go a
_ ByteCount
len ByteCount
n Ptr Word8
buf | ByteCount
len seq :: forall a b. a -> b -> b
`seq` ByteCount
n seq :: forall a b. a -> b -> b
`seq` Ptr Word8
buf seq :: forall a b. a -> b -> b
`seq` Bool
False = forall a. HasCallStack => a
undefined
    go a
z ByteCount
len ByteCount
n Ptr Word8
buf = do
        ByteCount
rc <- Fd -> Ptr Word8 -> ByteCount -> COff -> IO ByteCount
fdPreadBuf Fd
fd Ptr Word8
buf ByteCount
n (COff
offset forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
len)
        let len' :: ByteCount
len' = ByteCount
len forall a. Num a => a -> a -> a
+ ByteCount
rc
        case ByteCount
rc of
          ByteCount
_ | ByteCount
rc forall a. Eq a => a -> a -> Bool
== ByteCount
0 -> forall a. String -> IO a
ioErrorEOF String
_fdPreads
            | ByteCount
rc forall a. Eq a => a -> a -> Bool
== ByteCount
n -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
len') -- Finished.
            | Bool
otherwise ->
                case ByteCount -> a -> Maybe a
f ByteCount
len' a
z of
                Maybe a
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
len') -- Gave up.
                Just a
z' ->
                    a -> ByteCount -> ByteCount -> Ptr Word8 -> IO b
go a
z' ByteCount
len' (ByteCount
n forall a. Num a => a -> a -> a
- ByteCount
rc) (Ptr Word8
buf forall a b. Ptr a -> Int -> Ptr b
`plusPtr` forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
rc)

_fdPreads :: String
_fdPreads :: String
_fdPreads = String
"System.Posix.IO.ByteString.fdPreads"
{-# NOINLINE _fdPreads #-}

----------------------------------------------------------------
----------------------------------------------------------------
foreign import ccall safe "write"
    -- ssize_t write(int fildes, const void *buf, size_t nbyte);
    c_safe_write :: CInt -> Ptr CChar -> CSize -> IO CSsize


-- | Write data from memory to an 'Fd'. This is exactly equivalent
-- to the POSIX.1 @write(2)@ system call, except that we return 0
-- bytes written if the @ByteCount@ argument is less than or equal
-- to zero (instead of throwing an errno exception). /N.B./, this
-- behavior is different from the version in @unix-2.4.2.0@ which
-- doesn't check the byte count. If there are any errors, then they
-- are thrown as 'IOE.IOError' exceptions.
--
-- /Since: 0.3.0/
fdWriteBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory containing the data to write.
    -> ByteCount    -- ^ How many bytes to try to write.
    -> IO ByteCount -- ^ How many bytes were actually written.
fdWriteBuf :: Fd -> Ptr Word8 -> ByteCount -> IO ByteCount
fdWriteBuf Fd
fd Ptr Word8
buf ByteCount
nbytes
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ByteCount
0
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => String -> IO a -> IO a
C.throwErrnoIfMinus1Retry String
_fdWriteBuf
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CChar -> ByteCount -> IO CSsize
c_safe_write
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
buf)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)

_fdWriteBuf :: String
_fdWriteBuf :: String
_fdWriteBuf = String
"System.Posix.IO.ByteString.fdWriteBuf"
{-# NOINLINE _fdWriteBuf #-}


-- | Write data from memory to an 'Fd'. This is a variation of
-- 'fdWriteBuf' which returns errors with an 'Either' instead of
-- throwing exceptions.
--
-- /Since: 0.3.3/
tryFdWriteBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory containing the data to write.
    -> ByteCount    -- ^ How many bytes to try to write.
    -> IO (Either C.Errno ByteCount)
        -- ^ How many bytes were actually read (zero for EOF).
tryFdWriteBuf :: Fd -> Ptr Word8 -> ByteCount -> IO (Either Errno ByteCount)
tryFdWriteBuf Fd
fd Ptr Word8
buf ByteCount
nbytes
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right ByteCount
0)
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right forall a b. (Integral a, Num b) => a -> b
fromIntegral)
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => IO a -> IO (Either Errno a)
eitherErrnoIfMinus1Retry
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CChar -> ByteCount -> IO CSsize
c_safe_write
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
buf)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)

----------------------------------------------------------------
-- | Write a 'BS.ByteString' to an 'Fd'. The return value is the
-- total number of bytes actually written. This is exactly equivalent
-- to 'fdWriteBuf'; we just convert the @ByteString@ into its
-- underlying @Ptr Word8@ and @ByteCount@ components for passing
-- to 'fdWriteBuf'.
fdWrite
    :: Fd
    -> BS.ByteString -- ^ The string to write.
    -> IO ByteCount  -- ^ How many bytes were actually written.
fdWrite :: Fd -> ByteString -> IO ByteCount
fdWrite Fd
fd ByteString
s =
    -- N.B., BSU.unsafeUseAsCStringLen does zero copying. Use
    -- BS.useAsCStringLen if there's any chance fdWriteBuf might
    -- alter the buffer.
    forall a. ByteString -> (CStringLen -> IO a) -> IO a
BSU.unsafeUseAsCStringLen ByteString
s forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
buf,Int
len) -> do
        Fd -> Ptr Word8 -> ByteCount -> IO ByteCount
fdWriteBuf Fd
fd (forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
buf) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)


----------------------------------------------------------------
-- | Write a sequence of 'BS.ByteString's to an 'Fd'. The return
-- value is a triple of: the total number of bytes written, the
-- number of bytes written from the first of the remaining strings,
-- and the remaining (unwritten) strings. We return this triple
-- instead of a pair adjusting the head of the remaining strings
-- (i.e., removing the bytes already written) in case there is some
-- semantic significance to the way the input is split into chunks.
--
-- This version consumes the list lazily and will call 'fdWrite'
-- once for each @ByteString@, thus making /O(n)/ system calls.
-- This laziness allows the early parts of the list to be garbage
-- collected and prevents needing to hold the whole list of
-- @ByteString@s in memory at once. Compare against 'fdWritev'.
fdWrites
    :: Fd
    -> [BS.ByteString]
        -- ^ The strings to write.
    -> IO (ByteCount, ByteCount, [BS.ByteString])
        -- ^ The total number of bytes written, the number of bytes
        -- written from the first of the remaining strings, the
        -- remaining (unwritten) strings.
fdWrites :: Fd -> [ByteString] -> IO (ByteCount, ByteCount, [ByteString])
fdWrites Fd
fd = ByteCount
-> [ByteString] -> IO (ByteCount, ByteCount, [ByteString])
go ByteCount
0
    where
    -- We want to do a left fold in order to avoid stack overflows,
    -- but we need to have an early exit for incomplete writes
    -- (which normally requires a right fold). Hence this recursion.
    go :: ByteCount
-> [ByteString] -> IO (ByteCount, ByteCount, [ByteString])
go ByteCount
acc []         = forall (m :: * -> *) a. Monad m => a -> m a
return (ByteCount
acc, ByteCount
0, [])
    go ByteCount
acc ccs :: [ByteString]
ccs@(ByteString
c:[ByteString]
cs) =
        Fd -> ByteString -> IO ByteCount
fdWrite Fd
fd ByteString
c forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ByteCount
rc ->
        let acc' :: ByteCount
acc' = ByteCount
accforall a. Num a => a -> a -> a
+ByteCount
rc in ByteCount
acc' seq :: forall a b. a -> b -> b
`seq`
        if ByteCount
rc forall a. Eq a => a -> a -> Bool
== forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
BS.length ByteString
c)
            then ByteCount
-> [ByteString] -> IO (ByteCount, ByteCount, [ByteString])
go ByteCount
acc' [ByteString]
cs
            else forall (m :: * -> *) a. Monad m => a -> m a
return (ByteCount
acc', ByteCount
rc, [ByteString]
ccs)


----------------------------------------------------------------
foreign import ccall safe "writev"
    -- ssize_t writev(int fildes, const struct iovec *iov, int iovcnt);
    c_safe_writev :: CInt -> Ptr CIovec -> CInt -> IO CSsize
{-
-- N.B., c_safe_readv will throw errno=EINVAL
-- if iovcnt is less than or equal to 0, or greater than UIO_MAXIOV. (BUG: I have no idea where UIO_MAXIOV is defined! The web says it's in <linux/uio.h>, and some suggest using <limits.h>IOV_MAX or <limits.h>_XOPEN_IOV_MAX instead.)
-- <http://www.mail-archive.com/freebsd-current@freebsd.org/msg27878.html>
-- <http://www.mail-archive.com/naviserver-devel@lists.sourceforge.net/msg02237.html>
-- -- That last link says that glibc might transparently chop up larger values before sending to the kernel.
-- if one of the iov_len values in the iov array is negative.
-- if the sum of the iov_len values in the iov array overflows a 32-bit integer.
-}


-- | Write data from memory to an 'Fd'. This is exactly equivalent
-- to the XPG4.2 @writev(2)@ system call, except that we return 0
-- bytes written if the @Int@ argument is less than or equal to
-- zero (instead of throwing an 'C.eINVAL' exception). If there are
-- any errors, then they are thrown as 'IOE.IOError' exceptions.
--
-- TODO: better documentation.
--
-- /Since: 0.3.0/
fdWritevBuf
    :: Fd
    -> Ptr CIovec   -- ^ A C-style array of buffers to write.
    -> Int          -- ^ How many buffers there are.
    -> IO ByteCount -- ^ How many bytes were actually written.
fdWritevBuf :: Fd -> Ptr CIovec -> Int -> IO ByteCount
fdWritevBuf Fd
fd Ptr CIovec
bufs Int
len
    | Int
len forall a. Ord a => a -> a -> Bool
<= Int
0  = forall (m :: * -> *) a. Monad m => a -> m a
return ByteCount
0
    | Bool
otherwise =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => String -> IO a -> IO a
C.throwErrnoIfMinus1Retry String
_fdWritevBuf
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CIovec -> CInt -> IO CSsize
c_safe_writev (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd) Ptr CIovec
bufs (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)

_fdWritevBuf :: String
_fdWritevBuf :: String
_fdWritevBuf = String
"System.Posix.IO.ByteString.fdWritevBuf"
{-# NOINLINE _fdWritevBuf #-}


-- | Write data from memory to an 'Fd'. This is a variation of
-- 'fdWritevBuf' which returns errors with an 'Either' instead of
-- throwing exceptions.
--
-- /Since: 0.3.3/
tryFdWritevBuf
    :: Fd
    -> Ptr CIovec   -- ^ A C-style array of buffers to write.
    -> Int          -- ^ How many buffers there are.
    -> IO (Either C.Errno ByteCount)
        -- ^ How many bytes were actually read (zero for EOF).
tryFdWritevBuf :: Fd -> Ptr CIovec -> Int -> IO (Either Errno ByteCount)
tryFdWritevBuf Fd
fd Ptr CIovec
bufs Int
len
    | Int
len forall a. Ord a => a -> a -> Bool
<= Int
0  = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right ByteCount
0)
    | Bool
otherwise =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right forall a b. (Integral a, Num b) => a -> b
fromIntegral)
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => IO a -> IO (Either Errno a)
eitherErrnoIfMinus1Retry
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CIovec -> CInt -> IO CSsize
c_safe_writev (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd) Ptr CIovec
bufs (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)


----------------------------------------------------------------
-- | Write a sequence of 'BS.ByteString's to an 'Fd'. The return
-- value is the total number of bytes written. Unfortunately the
-- @writev(2)@ system call does not provide enough information to
-- return the triple that 'fdWrites' does.
--
-- This version will force the spine of the list, converting each
-- @ByteString@ into an @iovec@ (see 'CIovec'), and then call
-- 'fdWritevBuf'. This means we only make one system call, which
-- reduces the overhead of performing context switches. But it also
-- means that we must store the whole list of @ByteString@s in
-- memory at once, and that we must perform some allocation and
-- conversion. Compare against 'fdWrites'.
fdWritev
    :: Fd
    -> [BS.ByteString] -- ^ The strings to write.
    -> IO ByteCount    -- ^ How many bytes were actually written.
fdWritev :: Fd -> [ByteString] -> IO ByteCount
fdWritev Fd
fd [ByteString]
cs = do
    ByteCount
rc <- forall a b. Storable a => [a] -> (Int -> Ptr a -> IO b) -> IO b
FMA.withArrayLen (forall a b. (a -> b) -> [a] -> [b]
map ByteString -> CIovec
unsafeByteString2CIovec [ByteString]
cs) forall a b. (a -> b) -> a -> b
$ \Int
len Ptr CIovec
iovs ->
        Fd -> Ptr CIovec -> Int -> IO ByteCount
fdWritevBuf Fd
fd Ptr CIovec
iovs (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
    -- BUG: is this enough to actually hold onto them?
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ByteString -> IO ()
touchByteString [ByteString]
cs
    forall (m :: * -> *) a. Monad m => a -> m a
return ByteCount
rc


----------------------------------------------------------------
foreign import ccall safe "pwrite"
    -- ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
    c_safe_pwrite :: CInt -> Ptr Word8 -> CSize -> COff -> IO CSsize


-- | Write data from memory to a specified position in the 'Fd',
-- but without altering the position stored in the @Fd@. This is
-- exactly equivalent to the XPG4.2 @pwrite(2)@ system call, except
-- that we return 0 bytes written if the @ByteCount@ argument is
-- less than or equal to zero (instead of throwing an errno exception).
-- If there are any errors, then they are thrown as 'IOE.IOError'
-- exceptions.
--
-- /Since: 0.3.0/
fdPwriteBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory containing the data to write.
    -> ByteCount    -- ^ How many bytes to try to write.
    -> FileOffset   -- ^ Where to write the data to.
    -> IO ByteCount -- ^ How many bytes were actually written.
fdPwriteBuf :: Fd -> Ptr Word8 -> ByteCount -> COff -> IO ByteCount
fdPwriteBuf Fd
fd Ptr Word8
buf ByteCount
nbytes COff
offset
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ByteCount
0
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => String -> IO a -> IO a
C.throwErrnoIfMinus1Retry String
_fdPwriteBuf
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr Word8 -> ByteCount -> COff -> IO CSsize
c_safe_pwrite
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
buf)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral COff
offset)

_fdPwriteBuf :: String
_fdPwriteBuf :: String
_fdPwriteBuf = String
"System.Posix.IO.ByteString.fdPwriteBuf"
{-# NOINLINE _fdPwriteBuf #-}


-- | Write data from memory to a specified position in the 'Fd',
-- but without altering the position stored in the @Fd@. This is a
-- variation of 'fdPwriteBuf' which returns errors with an 'Either'
-- instead of throwing exceptions.
--
-- /Since: 0.3.3/
tryFdPwriteBuf
    :: Fd
    -> Ptr Word8    -- ^ Memory containing the data to write.
    -> ByteCount    -- ^ How many bytes to try to write.
    -> FileOffset   -- ^ Where to write the data to.
    -> IO (Either C.Errno ByteCount)
        -- ^ How many bytes were actually written.
tryFdPwriteBuf :: Fd -> Ptr Word8 -> ByteCount -> COff -> IO (Either Errno ByteCount)
tryFdPwriteBuf Fd
fd Ptr Word8
buf ByteCount
nbytes COff
offset
    | ByteCount
nbytes forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right ByteCount
0)
    | Bool
otherwise   =
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right forall a b. (Integral a, Num b) => a -> b
fromIntegral)
            forall a b. (a -> b) -> a -> b
$ forall a. (Eq a, Num a) => IO a -> IO (Either Errno a)
eitherErrnoIfMinus1Retry
                forall a b. (a -> b) -> a -> b
$ CInt -> Ptr Word8 -> ByteCount -> COff -> IO CSsize
c_safe_pwrite
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd)
                    (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
buf)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
nbytes)
                    (forall a b. (Integral a, Num b) => a -> b
fromIntegral COff
offset)


----------------------------------------------------------------
-- | Write data from memory to a specified position in the 'Fd',
-- but without altering the position stored in the @Fd@. This is
-- exactly equivalent to 'fdPwriteBuf'; we just convert the
-- @ByteString@ into its underlying @Ptr Word8@ and @ByteCount@
-- components for passing to 'fdPwriteBuf'.
--
-- /Since: 0.3.0/
fdPwrite
    :: Fd
    -> BS.ByteString -- ^ The string to write.
    -> FileOffset    -- ^ Where to write the data to.
    -> IO ByteCount  -- ^ How many bytes were actually written.
fdPwrite :: Fd -> ByteString -> COff -> IO ByteCount
fdPwrite Fd
fd ByteString
s COff
offset =
    -- N.B., BSU.unsafeUseAsCStringLen does zero copying. Use
    -- BS.useAsCStringLen if there's any chance fdPwriteBuf might
    -- alter the buffer.
    forall a. ByteString -> (CStringLen -> IO a) -> IO a
BSU.unsafeUseAsCStringLen ByteString
s forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
buf,Int
len) -> do
        Fd -> Ptr Word8 -> ByteCount -> COff -> IO ByteCount
fdPwriteBuf Fd
fd (forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
buf) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) COff
offset


----------------------------------------------------------------

mode2Int :: SeekMode -> CInt
mode2Int :: SeekMode -> CInt
mode2Int SeekMode
AbsoluteSeek = (CInt
0)
{-# LINE 761 "src/System/Posix/IO/ByteString.hsc" #-}
mode2Int RelativeSeek = (1)
{-# LINE 762 "src/System/Posix/IO/ByteString.hsc" #-}
mode2Int SeekFromEnd  = (2)
{-# LINE 763 "src/System/Posix/IO/ByteString.hsc" #-}


-- | Repositions the offset of the file descriptor according to the
-- offset and the seeking mode. This is exactly equivalent to the
-- POSIX.1 @lseek(2)@ system call. If there are any errors, then
-- they are thrown as 'IOE.IOError' exceptions.
--
-- This is the same as 'System.Posix.IO.fdSeek' in @unix-2.6.0.1@,
-- but provided here for consistency.
--
-- /Since: 0.3.5/
fdSeek :: Fd -> SeekMode -> FileOffset -> IO FileOffset
fdSeek :: Fd -> SeekMode -> COff -> IO COff
fdSeek Fd
fd SeekMode
mode COff
off =
    forall a. (Eq a, Num a) => String -> IO a -> IO a
C.throwErrnoIfMinus1 String
"fdSeek"
        forall a b. (a -> b) -> a -> b
$ CInt -> COff -> CInt -> IO COff
Base.c_lseek (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd) COff
off (SeekMode -> CInt
mode2Int SeekMode
mode)


-- | Repositions the offset of the file descriptor according to the
-- offset and the seeking mode. This is a variation of 'fdSeek'
-- which returns errors with an @Either@ instead of throwing
-- exceptions.
--
-- /Since: 0.3.5/
tryFdSeek :: Fd -> SeekMode -> FileOffset -> IO (Either C.Errno FileOffset)
tryFdSeek :: Fd -> SeekMode -> COff -> IO (Either Errno COff)
tryFdSeek Fd
fd SeekMode
mode COff
off =
    forall a. (Eq a, Num a) => IO a -> IO (Either Errno a)
eitherErrnoIfMinus1
        forall a b. (a -> b) -> a -> b
$ CInt -> COff -> CInt -> IO COff
Base.c_lseek (forall a b. (Integral a, Num b) => a -> b
fromIntegral Fd
fd) COff
off (SeekMode -> CInt
mode2Int SeekMode
mode)

----------------------------------------------------------------
----------------------------------------------------------- fin.