{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE CPP
, NoImplicitPrelude
, BangPatterns
, RankNTypes
#-}
{-# OPTIONS_GHC -Wno-identities #-}
{-# OPTIONS_HADDOCK not-home #-}
module GHC.Internal.IO.FD (
FD(..),
openFileWith, openFile, mkFD, release,
setNonBlockingMode,
readRawBufferPtr, readRawBufferPtrNoBlock, writeRawBufferPtr,
stdin, stdout, stderr
) where
import GHC.Internal.Base
import GHC.Internal.Bits
import GHC.Internal.Num
import GHC.Internal.Real
import GHC.Internal.Show
import GHC.Internal.Enum
import GHC.Internal.Word
import GHC.Internal.Int
import GHC.Internal.Ptr
import GHC.Internal.IO
import GHC.Internal.IO.IOMode
import GHC.Internal.IO.Buffer
import GHC.Internal.IO.BufferedIO
import qualified GHC.Internal.IO.Device
import GHC.Internal.IO.Device (SeekMode(..), IODeviceType(..))
import GHC.Internal.Conc.IO
import GHC.Internal.IO.Exception
#if defined(mingw32_HOST_OS)
import GHC.Internal.Windows
import GHC.Internal.Data.Bool
import GHC.Internal.IO.SubSystem ((<!>))
import GHC.Internal.Foreign.Storable
#endif
import GHC.Internal.Foreign.C.Types
import GHC.Internal.Foreign.C.Error
import GHC.Internal.Foreign.Marshal.Utils
import GHC.Internal.Foreign.Marshal.Alloc (allocaBytes)
import qualified GHC.Internal.System.Posix.Internals
import GHC.Internal.System.Posix.Internals hiding (FD, setEcho, getEcho)
import GHC.Internal.System.Posix.Types
c_DEBUG_DUMP :: Bool
c_DEBUG_DUMP :: Bool
c_DEBUG_DUMP = Bool
False
clampWriteSize, clampReadSize :: Int -> Int
clampWriteSize :: Int -> Int
clampWriteSize = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
0x7ffff000
clampReadSize :: Int -> Int
clampReadSize = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
0x7ffff000
data FD = FD {
FD -> CInt
fdFD :: {-# UNPACK #-} !CInt,
#if defined(mingw32_HOST_OS)
FD -> Int
fdIsSocket_ :: {-# UNPACK #-} !Int
#else
fdIsNonBlocking :: {-# UNPACK #-} !Int
#endif
}
#if defined(mingw32_HOST_OS)
fdIsSocket :: FD -> Bool
fdIsSocket :: FD -> Bool
fdIsSocket FD
fd = FD -> Int
fdIsSocket_ FD
fd Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
#endif
instance Show FD where
show :: FD -> String
show FD
fd = CInt -> String
forall a. Show a => a -> String
show (FD -> CInt
fdFD FD
fd)
{-# INLINE ifSupported #-}
ifSupported :: String -> a -> a
#if defined(mingw32_HOST_OS)
ifSupported :: forall a. String -> a -> a
ifSupported String
s a
a = a
a a -> a -> a
forall a. a -> a -> a
<!> (String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"FD:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" not supported")
#else
ifSupported _ = id
#endif
instance GHC.Internal.IO.Device.RawIO FD where
read :: FD -> Ptr Word8 -> Word64 -> Int -> IO Int
read = String
-> (FD -> Ptr Word8 -> Word64 -> Int -> IO Int)
-> FD
-> Ptr Word8
-> Word64
-> Int
-> IO Int
forall a. String -> a -> a
ifSupported String
"fdRead" FD -> Ptr Word8 -> Word64 -> Int -> IO Int
fdRead
readNonBlocking :: FD -> Ptr Word8 -> Word64 -> Int -> IO (Maybe Int)
readNonBlocking = String
-> (FD -> Ptr Word8 -> Word64 -> Int -> IO (Maybe Int))
-> FD
-> Ptr Word8
-> Word64
-> Int
-> IO (Maybe Int)
forall a. String -> a -> a
ifSupported String
"fdReadNonBlocking" FD -> Ptr Word8 -> Word64 -> Int -> IO (Maybe Int)
fdReadNonBlocking
write :: FD -> Ptr Word8 -> Word64 -> Int -> IO ()
write = String
-> (FD -> Ptr Word8 -> Word64 -> Int -> IO ())
-> FD
-> Ptr Word8
-> Word64
-> Int
-> IO ()
forall a. String -> a -> a
ifSupported String
"fdWrite" FD -> Ptr Word8 -> Word64 -> Int -> IO ()
fdWrite
writeNonBlocking :: FD -> Ptr Word8 -> Word64 -> Int -> IO Int
writeNonBlocking = String
-> (FD -> Ptr Word8 -> Word64 -> Int -> IO Int)
-> FD
-> Ptr Word8
-> Word64
-> Int
-> IO Int
forall a. String -> a -> a
ifSupported String
"fdWriteNonBlocking" FD -> Ptr Word8 -> Word64 -> Int -> IO Int
fdWriteNonBlocking
instance GHC.Internal.IO.Device.IODevice FD where
ready :: FD -> Bool -> Int -> IO Bool
ready = String
-> (FD -> Bool -> Int -> IO Bool) -> FD -> Bool -> Int -> IO Bool
forall a. String -> a -> a
ifSupported String
"ready" FD -> Bool -> Int -> IO Bool
ready
close :: FD -> IO ()
close = String -> (FD -> IO ()) -> FD -> IO ()
forall a. String -> a -> a
ifSupported String
"close" FD -> IO ()
close
isTerminal :: FD -> IO Bool
isTerminal = String -> (FD -> IO Bool) -> FD -> IO Bool
forall a. String -> a -> a
ifSupported String
"isTerm" FD -> IO Bool
isTerminal
isSeekable :: FD -> IO Bool
isSeekable = String -> (FD -> IO Bool) -> FD -> IO Bool
forall a. String -> a -> a
ifSupported String
"isSeek" FD -> IO Bool
isSeekable
seek :: FD -> SeekMode -> Integer -> IO Integer
seek = String
-> (FD -> SeekMode -> Integer -> IO Integer)
-> FD
-> SeekMode
-> Integer
-> IO Integer
forall a. String -> a -> a
ifSupported String
"seek" FD -> SeekMode -> Integer -> IO Integer
seek
tell :: FD -> IO Integer
tell = String -> (FD -> IO Integer) -> FD -> IO Integer
forall a. String -> a -> a
ifSupported String
"tell" FD -> IO Integer
tell
getSize :: FD -> IO Integer
getSize = String -> (FD -> IO Integer) -> FD -> IO Integer
forall a. String -> a -> a
ifSupported String
"getSize" FD -> IO Integer
getSize
setSize :: FD -> Integer -> IO ()
setSize = String -> (FD -> Integer -> IO ()) -> FD -> Integer -> IO ()
forall a. String -> a -> a
ifSupported String
"setSize" FD -> Integer -> IO ()
setSize
setEcho :: FD -> Bool -> IO ()
setEcho = String -> (FD -> Bool -> IO ()) -> FD -> Bool -> IO ()
forall a. String -> a -> a
ifSupported String
"setEcho" FD -> Bool -> IO ()
setEcho
getEcho :: FD -> IO Bool
getEcho = String -> (FD -> IO Bool) -> FD -> IO Bool
forall a. String -> a -> a
ifSupported String
"getEcho" FD -> IO Bool
getEcho
setRaw :: FD -> Bool -> IO ()
setRaw = String -> (FD -> Bool -> IO ()) -> FD -> Bool -> IO ()
forall a. String -> a -> a
ifSupported String
"setRaw" FD -> Bool -> IO ()
setRaw
devType :: FD -> IO IODeviceType
devType = String -> (FD -> IO IODeviceType) -> FD -> IO IODeviceType
forall a. String -> a -> a
ifSupported String
"devType" FD -> IO IODeviceType
devType
dup :: FD -> IO FD
dup = String -> (FD -> IO FD) -> FD -> IO FD
forall a. String -> a -> a
ifSupported String
"dup" FD -> IO FD
dup
dup2 :: FD -> FD -> IO FD
dup2 = String -> (FD -> FD -> IO FD) -> FD -> FD -> IO FD
forall a. String -> a -> a
ifSupported String
"dup2" FD -> FD -> IO FD
dup2
dEFAULT_FD_BUFFER_SIZE :: Int
dEFAULT_FD_BUFFER_SIZE :: Int
dEFAULT_FD_BUFFER_SIZE = Int
8192
instance BufferedIO FD where
newBuffer :: FD -> BufferState -> IO (Buffer Word8)
newBuffer FD
_dev BufferState
state = String -> IO (Buffer Word8) -> IO (Buffer Word8)
forall a. String -> a -> a
ifSupported String
"newBuf" (IO (Buffer Word8) -> IO (Buffer Word8))
-> IO (Buffer Word8) -> IO (Buffer Word8)
forall a b. (a -> b) -> a -> b
$ Int -> BufferState -> IO (Buffer Word8)
newByteBuffer Int
dEFAULT_FD_BUFFER_SIZE BufferState
state
fillReadBuffer :: FD -> Buffer Word8 -> IO (Int, Buffer Word8)
fillReadBuffer FD
fd Buffer Word8
buf = String -> IO (Int, Buffer Word8) -> IO (Int, Buffer Word8)
forall a. String -> a -> a
ifSupported String
"readBuf" (IO (Int, Buffer Word8) -> IO (Int, Buffer Word8))
-> IO (Int, Buffer Word8) -> IO (Int, Buffer Word8)
forall a b. (a -> b) -> a -> b
$ FD -> Buffer Word8 -> IO (Int, Buffer Word8)
readBuf' FD
fd Buffer Word8
buf
fillReadBuffer0 :: FD -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)
fillReadBuffer0 FD
fd Buffer Word8
buf = String
-> IO (Maybe Int, Buffer Word8) -> IO (Maybe Int, Buffer Word8)
forall a. String -> a -> a
ifSupported String
"readBufNonBlock" (IO (Maybe Int, Buffer Word8) -> IO (Maybe Int, Buffer Word8))
-> IO (Maybe Int, Buffer Word8) -> IO (Maybe Int, Buffer Word8)
forall a b. (a -> b) -> a -> b
$ FD -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)
forall dev.
RawIO dev =>
dev -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)
readBufNonBlocking FD
fd Buffer Word8
buf
flushWriteBuffer :: FD -> Buffer Word8 -> IO (Buffer Word8)
flushWriteBuffer FD
fd Buffer Word8
buf = String -> IO (Buffer Word8) -> IO (Buffer Word8)
forall a. String -> a -> a
ifSupported String
"writeBuf" (IO (Buffer Word8) -> IO (Buffer Word8))
-> IO (Buffer Word8) -> IO (Buffer Word8)
forall a b. (a -> b) -> a -> b
$ FD -> Buffer Word8 -> IO (Buffer Word8)
writeBuf' FD
fd Buffer Word8
buf
flushWriteBuffer0 :: FD -> Buffer Word8 -> IO (Int, Buffer Word8)
flushWriteBuffer0 FD
fd Buffer Word8
buf = String -> IO (Int, Buffer Word8) -> IO (Int, Buffer Word8)
forall a. String -> a -> a
ifSupported String
"writeBufNonBlock" (IO (Int, Buffer Word8) -> IO (Int, Buffer Word8))
-> IO (Int, Buffer Word8) -> IO (Int, Buffer Word8)
forall a b. (a -> b) -> a -> b
$ FD -> Buffer Word8 -> IO (Int, Buffer Word8)
forall dev.
RawIO dev =>
dev -> Buffer Word8 -> IO (Int, Buffer Word8)
writeBufNonBlocking FD
fd Buffer Word8
buf
readBuf' :: FD -> Buffer Word8 -> IO (Int, Buffer Word8)
readBuf' :: FD -> Buffer Word8 -> IO (Int, Buffer Word8)
readBuf' FD
fd Buffer Word8
buf = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
c_DEBUG_DUMP (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
puts (String
"readBuf fd=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ FD -> String
forall a. Show a => a -> String
show FD
fd String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Buffer Word8 -> String
forall a. Buffer a -> String
summaryBuffer Buffer Word8
buf String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n")
(r,buf') <- FD -> Buffer Word8 -> IO (Int, Buffer Word8)
forall dev.
RawIO dev =>
dev -> Buffer Word8 -> IO (Int, Buffer Word8)
readBuf FD
fd Buffer Word8
buf
when c_DEBUG_DUMP $
puts ("after: " ++ summaryBuffer buf' ++ "\n")
return (r,buf')
writeBuf' :: FD -> Buffer Word8 -> IO (Buffer Word8)
writeBuf' :: FD -> Buffer Word8 -> IO (Buffer Word8)
writeBuf' FD
fd Buffer Word8
buf = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
c_DEBUG_DUMP (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
puts (String
"writeBuf fd=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ FD -> String
forall a. Show a => a -> String
show FD
fd String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Buffer Word8 -> String
forall a. Buffer a -> String
summaryBuffer Buffer Word8
buf String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n")
FD -> Buffer Word8 -> IO (Buffer Word8)
forall dev. RawIO dev => dev -> Buffer Word8 -> IO (Buffer Word8)
writeBuf FD
fd Buffer Word8
buf
openFileWith
:: FilePath
-> IOMode
-> Bool
-> (FD -> IODeviceType -> IO r)
-> ((forall x. IO x -> IO x) -> r -> IO s)
-> IO s
openFileWith :: forall r s.
String
-> IOMode
-> Bool
-> (FD -> IODeviceType -> IO r)
-> ((forall x. IO x -> IO x) -> r -> IO s)
-> IO s
openFileWith String
filepath IOMode
iomode Bool
non_blocking FD -> IODeviceType -> IO r
act1 (forall x. IO x -> IO x) -> r -> IO s
act2 =
String -> (CWString -> IO s) -> IO s
forall a. String -> (CWString -> IO a) -> IO a
withFilePath String
filepath ((CWString -> IO s) -> IO s) -> (CWString -> IO s) -> IO s
forall a b. (a -> b) -> a -> b
$ \ CWString
f ->
let
oflags1 :: CInt
oflags1 = case IOMode
iomode of
IOMode
ReadMode -> CInt
read_flags
IOMode
WriteMode -> CInt
write_flags
IOMode
ReadWriteMode -> CInt
rw_flags
IOMode
AppendMode -> CInt
append_flags
#if defined(mingw32_HOST_OS)
binary_flags :: CInt
binary_flags = CInt
o_BINARY
#else
binary_flags = 0
#endif
oflags2 :: CInt
oflags2 = CInt
oflags1 CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. CInt
binary_flags
oflags :: CInt
oflags | Bool
non_blocking = CInt
oflags2 CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. CInt
nonblock_flags
| Bool
otherwise = CInt
oflags2
in do
oflags' <- CInt -> IO CInt
forall a. a -> IO a
evaluate CInt
oflags
mask $ \forall x. IO x -> IO x
restore -> do
fileno <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
"openFile" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$
CWString -> CInt -> CMode -> IO CInt
c_interruptible_open CWString
f CInt
oflags' CMode
0o666
(fD,fd_type) <- mkFD fileno iomode Nothing
False
non_blocking `onException` c_close fileno
when (iomode == WriteMode && fd_type == RegularFile) $
setSize fD 0 `onException` close fD
carry <- restore (act1 fD fd_type) `onException` close fD
act2 restore carry
openFile
:: FilePath
-> IOMode
-> Bool
-> IO (FD,IODeviceType)
openFile :: String -> IOMode -> Bool -> IO (FD, IODeviceType)
openFile String
filepath IOMode
iomode Bool
non_blocking =
String
-> IOMode
-> Bool
-> (FD -> IODeviceType -> IO (FD, IODeviceType))
-> ((forall x. IO x -> IO x)
-> (FD, IODeviceType) -> IO (FD, IODeviceType))
-> IO (FD, IODeviceType)
forall r s.
String
-> IOMode
-> Bool
-> (FD -> IODeviceType -> IO r)
-> ((forall x. IO x -> IO x) -> r -> IO s)
-> IO s
openFileWith String
filepath IOMode
iomode Bool
non_blocking
(\ FD
fd IODeviceType
fd_type -> (FD, IODeviceType) -> IO (FD, IODeviceType)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FD
fd, IODeviceType
fd_type)) (\forall x. IO x -> IO x
_ (FD, IODeviceType)
r -> (FD, IODeviceType) -> IO (FD, IODeviceType)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FD, IODeviceType)
r)
std_flags, output_flags, read_flags, write_flags, rw_flags,
append_flags, nonblock_flags :: CInt
std_flags :: CInt
std_flags = CInt
o_NOCTTY
output_flags :: CInt
output_flags = CInt
std_flags CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. CInt
o_CREAT
read_flags :: CInt
read_flags = CInt
std_flags CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. CInt
o_RDONLY
write_flags :: CInt
write_flags = CInt
output_flags CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. CInt
o_WRONLY
rw_flags :: CInt
rw_flags = CInt
output_flags CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. CInt
o_RDWR
append_flags :: CInt
append_flags = CInt
write_flags CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. CInt
o_APPEND
nonblock_flags :: CInt
nonblock_flags = CInt
o_NONBLOCK
mkFD :: CInt
-> IOMode
-> Maybe (IODeviceType, CDev, CIno)
-> Bool
-> Bool
-> IO (FD,IODeviceType)
mkFD :: CInt
-> IOMode
-> Maybe (IODeviceType, CDev, CIno)
-> Bool
-> Bool
-> IO (FD, IODeviceType)
mkFD CInt
fd IOMode
iomode Maybe (IODeviceType, CDev, CIno)
mb_stat Bool
is_socket Bool
is_nonblock = do
let (Bool, Bool)
_ = (Bool
is_socket, Bool
is_nonblock)
(fd_type,dev,ino) <-
case Maybe (IODeviceType, CDev, CIno)
mb_stat of
Maybe (IODeviceType, CDev, CIno)
Nothing -> CInt -> IO (IODeviceType, CDev, CIno)
fdStat CInt
fd
Just (IODeviceType, CDev, CIno)
stat -> (IODeviceType, CDev, CIno) -> IO (IODeviceType, CDev, CIno)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (IODeviceType, CDev, CIno)
stat
let write = case IOMode
iomode of
IOMode
ReadMode -> Bool
False
IOMode
_ -> Bool
True
case fd_type of
IODeviceType
Directory ->
IOException -> IO ()
forall a. HasCallStack => IOException -> IO a
ioException (Maybe Handle
-> IOErrorType
-> String
-> String
-> Maybe CInt
-> Maybe String
-> IOException
IOError Maybe Handle
forall a. Maybe a
Nothing IOErrorType
InappropriateType String
"openFile"
String
"is a directory" Maybe CInt
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing)
IODeviceType
RegularFile -> do
(unique_dev, unique_ino) <- CInt -> CDev -> CIno -> IO (Word64, Word64)
getUniqueFileInfo CInt
fd CDev
dev CIno
ino
r <- lockFile (fromIntegral fd) unique_dev unique_ino
(fromBool write)
when (r == -1) $
ioException (IOError Nothing ResourceBusy "openFile"
"file is locked" Nothing Nothing)
IODeviceType
_other_type -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
#if defined(mingw32_HOST_OS)
when (not is_socket) $ setmode fd True >> return ()
#endif
return (FD{ fdFD = fd,
#if !defined(mingw32_HOST_OS)
fdIsNonBlocking = fromEnum (is_nonblock && fd_type /= RegularFile && fd_type /= RawDevice)
#else
fdIsSocket_ = fromEnum is_socket
#endif
},
fd_type)
getUniqueFileInfo :: CInt -> CDev -> CIno -> IO (Word64, Word64)
#if !defined(mingw32_HOST_OS)
getUniqueFileInfo _ dev ino = return (fromIntegral dev, fromIntegral ino)
#else
getUniqueFileInfo :: CInt -> CDev -> CIno -> IO (Word64, Word64)
getUniqueFileInfo CInt
fd CDev
_ CIno
_ = do
Word64
-> (Ptr Word64 -> IO (Word64, Word64)) -> IO (Word64, Word64)
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with Word64
0 ((Ptr Word64 -> IO (Word64, Word64)) -> IO (Word64, Word64))
-> (Ptr Word64 -> IO (Word64, Word64)) -> IO (Word64, Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word64
devptr -> do
Word64
-> (Ptr Word64 -> IO (Word64, Word64)) -> IO (Word64, Word64)
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with Word64
0 ((Ptr Word64 -> IO (Word64, Word64)) -> IO (Word64, Word64))
-> (Ptr Word64 -> IO (Word64, Word64)) -> IO (Word64, Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word64
inoptr -> do
CInt -> Ptr Word64 -> Ptr Word64 -> IO ()
c_getUniqueFileInfo CInt
fd Ptr Word64
devptr Ptr Word64
inoptr
(Word64 -> Word64 -> (Word64, Word64))
-> IO Word64 -> IO Word64 -> IO (Word64, Word64)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek Ptr Word64
devptr) (Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek Ptr Word64
inoptr)
#endif
#if defined(mingw32_HOST_OS)
foreign import ccall unsafe "__hscore_setmode"
setmode :: CInt -> Bool -> IO CInt
#endif
stdFD :: CInt -> FD
stdFD :: CInt -> FD
stdFD CInt
fd = FD { fdFD :: CInt
fdFD = CInt
fd,
#if defined(mingw32_HOST_OS)
fdIsSocket_ :: Int
fdIsSocket_ = Int
0
#else
fdIsNonBlocking = 0
#endif
}
stdin, stdout, stderr :: FD
stdin :: FD
stdin = CInt -> FD
stdFD CInt
0
stdout :: FD
stdout = CInt -> FD
stdFD CInt
1
stderr :: FD
stderr = CInt -> FD
stdFD CInt
2
close :: FD -> IO ()
close :: FD -> IO ()
close FD
fd =
do let closer :: a -> IO ()
closer a
realFd =
String -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_ String
"GHC.Internal.IO.FD.close" (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$
#if defined(mingw32_HOST_OS)
if FD -> Bool
fdIsSocket FD
fd then
CInt -> IO CInt
c_closesocket (a -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
realFd)
else
#endif
CInt -> IO CInt
c_close (a -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
realFd)
FD -> IO ()
release FD
fd
(Fd -> IO ()) -> Fd -> IO ()
closeFdWith Fd -> IO ()
forall {a}. Integral a => a -> IO ()
closer (CInt -> Fd
forall a b. (Integral a, Num b) => a -> b
fromIntegral (FD -> CInt
fdFD FD
fd))
release :: FD -> IO ()
release :: FD -> IO ()
release FD
fd = do _ <- Word64 -> IO CInt
unlockFile (CInt -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Word64) -> CInt -> Word64
forall a b. (a -> b) -> a -> b
$ FD -> CInt
fdFD FD
fd)
return ()
#if defined(mingw32_HOST_OS)
foreign import ccall unsafe "HsBase.h closesocket"
c_closesocket :: CInt -> IO CInt
#endif
isSeekable :: FD -> IO Bool
isSeekable :: FD -> IO Bool
isSeekable FD
fd = do
t <- FD -> IO IODeviceType
devType FD
fd
return (t == RegularFile || t == RawDevice)
seek :: FD -> SeekMode -> Integer -> IO Integer
seek :: FD -> SeekMode -> Integer -> IO Integer
seek FD
fd SeekMode
mode Integer
off = Int64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Integer) -> IO Int64 -> IO Integer
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap`
(String -> IO Int64 -> IO Int64
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
"seek" (IO Int64 -> IO Int64) -> IO Int64 -> IO Int64
forall a b. (a -> b) -> a -> b
$
CInt -> Int64 -> CInt -> IO Int64
c_lseek (FD -> CInt
fdFD FD
fd) (Integer -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
off) CInt
seektype)
where
seektype :: CInt
seektype :: CInt
seektype = case SeekMode
mode of
SeekMode
AbsoluteSeek -> CInt
sEEK_SET
SeekMode
RelativeSeek -> CInt
sEEK_CUR
SeekMode
SeekFromEnd -> CInt
sEEK_END
tell :: FD -> IO Integer
tell :: FD -> IO Integer
tell FD
fd =
Int64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Integer) -> IO Int64 -> IO Integer
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap`
(String -> IO Int64 -> IO Int64
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
"hGetPosn" (IO Int64 -> IO Int64) -> IO Int64 -> IO Int64
forall a b. (a -> b) -> a -> b
$
CInt -> Int64 -> CInt -> IO Int64
c_lseek (FD -> CInt
fdFD FD
fd) Int64
0 CInt
sEEK_CUR)
getSize :: FD -> IO Integer
getSize :: FD -> IO Integer
getSize FD
fd = CInt -> IO Integer
fdFileSize (FD -> CInt
fdFD FD
fd)
setSize :: FD -> Integer -> IO ()
setSize :: FD -> Integer -> IO ()
setSize FD
fd Integer
size =
(CInt -> Bool) -> String -> IO CInt -> IO ()
forall a. (a -> Bool) -> String -> IO a -> IO ()
throwErrnoIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/=CInt
0) String
"GHC.Internal.IO.FD.setSize" (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$
CInt -> COff -> IO CInt
c_ftruncate (FD -> CInt
fdFD FD
fd) (Integer -> COff
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
size)
devType :: FD -> IO IODeviceType
devType :: FD -> IO IODeviceType
devType FD
fd = do (ty,_,_) <- CInt -> IO (IODeviceType, CDev, CIno)
fdStat (FD -> CInt
fdFD FD
fd); return ty
dup :: FD -> IO FD
dup :: FD -> IO FD
dup FD
fd = do
newfd <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1 String
"GHC.Internal.IO.FD.dup" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ CInt -> IO CInt
c_dup (FD -> CInt
fdFD FD
fd)
return fd{ fdFD = newfd }
dup2 :: FD -> FD -> IO FD
dup2 :: FD -> FD -> IO FD
dup2 FD
fd FD
fdto = do
String -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1_ String
"GHC.Internal.IO.FD.dup2" (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$
CInt -> CInt -> IO CInt
c_dup2 (FD -> CInt
fdFD FD
fd) (FD -> CInt
fdFD FD
fdto)
FD -> IO FD
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return FD
fd{ fdFD = fdFD fdto }
setNonBlockingMode :: FD -> Bool -> IO FD
setNonBlockingMode :: FD -> Bool -> IO FD
setNonBlockingMode FD
fd Bool
set = do
is_nonblock <-
if Bool
set
then do
Int -> (Ptr CStat -> IO Bool) -> IO Bool
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
sizeof_stat ((Ptr CStat -> IO Bool) -> IO Bool)
-> (Ptr CStat -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ Ptr CStat
p_stat -> do
String -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_ String
"fileSize" (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$
CInt -> Ptr CStat -> IO CInt
c_fstat (FD -> CInt
fdFD FD
fd) Ptr CStat
p_stat
fd_type <- Ptr CStat -> IO (Maybe IODeviceType)
statGetType_maybe Ptr CStat
p_stat
pure $ fd_type /= Just RegularFile && fd_type /= Just RawDevice
else Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
setNonBlockingFD (fdFD fd) is_nonblock
#if defined(mingw32_HOST_OS)
return fd
#else
return fd{ fdIsNonBlocking = fromEnum is_nonblock }
#endif
ready :: FD -> Bool -> Int -> IO Bool
ready :: FD -> Bool -> Int -> IO Bool
ready FD
fd Bool
write Int
msecs = do
r <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
"GHC.Internal.IO.FD.ready" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$
CInt -> CBool -> Int64 -> CBool -> IO CInt
fdReady (FD -> CInt
fdFD FD
fd) (Int -> CBool
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CBool) -> Int -> CBool
forall a b. (a -> b) -> a -> b
$ Bool -> Int
forall a. Enum a => a -> Int
fromEnum (Bool -> Int) -> Bool -> Int
forall a b. (a -> b) -> a -> b
$ Bool
write)
(Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
msecs)
#if defined(mingw32_HOST_OS)
(Int -> CBool
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CBool) -> Int -> CBool
forall a b. (a -> b) -> a -> b
$ Bool -> Int
forall a. Enum a => a -> Int
fromEnum (Bool -> Int) -> Bool -> Int
forall a b. (a -> b) -> a -> b
$ FD -> Bool
fdIsSocket FD
fd)
#else
0
#endif
return (toEnum (fromIntegral r))
foreign import ccall safe "fdReady"
fdReady :: CInt -> CBool -> Int64 -> CBool -> IO CInt
isTerminal :: FD -> IO Bool
isTerminal :: FD -> IO Bool
isTerminal FD
fd =
#if defined(mingw32_HOST_OS)
if FD -> Bool
fdIsSocket FD
fd then Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
else CInt -> IO CInt
is_console (FD -> CInt
fdFD FD
fd) IO CInt -> (CInt -> IO Bool) -> IO Bool
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return(Bool -> IO Bool) -> (CInt -> Bool) -> CInt -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.CInt -> Bool
forall a. (Eq a, Num a) => a -> Bool
toBool
#else
c_isatty (fdFD fd) >>= return.toBool
#endif
setEcho :: FD -> Bool -> IO ()
setEcho :: FD -> Bool -> IO ()
setEcho FD
fd Bool
on = CInt -> Bool -> IO ()
GHC.Internal.System.Posix.Internals.setEcho (FD -> CInt
fdFD FD
fd) Bool
on
getEcho :: FD -> IO Bool
getEcho :: FD -> IO Bool
getEcho FD
fd = CInt -> IO Bool
GHC.Internal.System.Posix.Internals.getEcho (FD -> CInt
fdFD FD
fd)
setRaw :: FD -> Bool -> IO ()
setRaw :: FD -> Bool -> IO ()
setRaw FD
fd Bool
raw = CInt -> Bool -> IO ()
GHC.Internal.System.Posix.Internals.setCooked (FD -> CInt
fdFD FD
fd) (Bool -> Bool
not Bool
raw)
fdRead :: FD -> Ptr Word8 -> Word64 -> Int -> IO Int
fdRead :: FD -> Ptr Word8 -> Word64 -> Int -> IO Int
fdRead FD
fd Ptr Word8
ptr Word64
_offset Int
bytes
= do { r <- String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtr String
"GHC.Internal.IO.FD.fdRead" FD
fd Ptr Word8
ptr Int
0
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CSize) -> Int -> CSize
forall a b. (a -> b) -> a -> b
$ Int -> Int
clampReadSize Int
bytes)
; return (fromIntegral r) }
fdReadNonBlocking :: FD -> Ptr Word8 -> Word64 -> Int -> IO (Maybe Int)
fdReadNonBlocking :: FD -> Ptr Word8 -> Word64 -> Int -> IO (Maybe Int)
fdReadNonBlocking FD
fd Ptr Word8
ptr Word64
_offset Int
bytes = do
r <- String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtrNoBlock String
"GHC.Internal.IO.FD.fdReadNonBlocking" FD
fd Ptr Word8
ptr
Int
0 (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CSize) -> Int -> CSize
forall a b. (a -> b) -> a -> b
$ Int -> Int
clampReadSize Int
bytes)
case fromIntegral r of
(-1) -> Maybe Int -> IO (Maybe Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Int
forall a. Maybe a
Nothing)
Int
n -> Maybe Int -> IO (Maybe Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
n)
fdWrite :: FD -> Ptr Word8 -> Word64 -> Int -> IO ()
fdWrite :: FD -> Ptr Word8 -> Word64 -> Int -> IO ()
fdWrite FD
fd Ptr Word8
ptr Word64
_offset Int
bytes = do
res <- String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtr String
"GHC.Internal.IO.FD.fdWrite" FD
fd Ptr Word8
ptr Int
0
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CSize) -> Int -> CSize
forall a b. (a -> b) -> a -> b
$ Int -> Int
clampWriteSize Int
bytes)
let res' = CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
res
if res' < bytes
then fdWrite fd (ptr `plusPtr` res') (_offset + fromIntegral res') (bytes - res')
else return ()
fdWriteNonBlocking :: FD -> Ptr Word8 -> Word64 -> Int -> IO Int
fdWriteNonBlocking :: FD -> Ptr Word8 -> Word64 -> Int -> IO Int
fdWriteNonBlocking FD
fd Ptr Word8
ptr Word64
_offset Int
bytes = do
res <- String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtrNoBlock String
"GHC.Internal.IO.FD.fdWriteNonBlocking" FD
fd Ptr Word8
ptr Int
0
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CSize) -> Int -> CSize
forall a b. (a -> b) -> a -> b
$ Int -> Int
clampWriteSize Int
bytes)
return (fromIntegral res)
#if !defined(mingw32_HOST_OS)
readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO Int
readRawBufferPtr loc !fd !buf !off !len
#if defined(javascript_HOST_ARCH)
= fmap fromIntegral . mask_ $
throwErrnoIfMinus1 loc (c_read (fdFD fd) (buf `plusPtr` off) len)
#else
| isNonBlocking fd = unsafe_read
| otherwise = do r <- throwErrnoIfMinus1 loc
(unsafe_fdReady (fdFD fd) 0 0 0)
if r /= 0
then read
else do threadWaitRead (fromIntegral (fdFD fd)); read
where
do_read call = fromIntegral `fmap`
throwErrnoIfMinus1RetryMayBlock loc call
(threadWaitRead (fromIntegral (fdFD fd)))
read = if threaded then safe_read else unsafe_read
unsafe_read = do_read (c_read (fdFD fd) (buf `plusPtr` off) len)
safe_read = do_read (c_safe_read (fdFD fd) (buf `plusPtr` off) len)
#endif
readRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO Int
readRawBufferPtrNoBlock loc !fd !buf !off !len
#if defined(javascript_HOST_ARCH)
= mask_ $ do
r <- throwErrnoIfMinus1 loc (c_read (fdFD fd) (buf `plusPtr` off) len)
case r of
(-1) -> return 0
0 -> return (-1)
n -> return (fromIntegral n)
#else
| isNonBlocking fd = unsafe_read
| otherwise = do r <- unsafe_fdReady (fdFD fd) 0 0 0
if r /= 0 then safe_read
else return 0
where
do_read call = do r <- throwErrnoIfMinus1RetryOnBlock loc call (return (-1))
case r of
(-1) -> return 0
0 -> return (-1)
n -> return (fromIntegral n)
unsafe_read = do_read (c_read (fdFD fd) (buf `plusPtr` off) len)
safe_read = do_read (c_safe_read (fdFD fd) (buf `plusPtr` off) len)
#endif
writeRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtr loc !fd !buf !off !len
#if defined(javascript_HOST_ARCH)
= fmap fromIntegral . mask_ $
throwErrnoIfMinus1 loc (c_write (fdFD fd) (buf `plusPtr` off) len)
#else
| isNonBlocking fd = unsafe_write
| otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0
if r /= 0
then write
else do threadWaitWrite (fromIntegral (fdFD fd)); write
where
do_write call = fromIntegral `fmap`
throwErrnoIfMinus1RetryMayBlock loc call
(threadWaitWrite (fromIntegral (fdFD fd)))
write = if threaded then safe_write else unsafe_write
unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len)
safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)
#endif
writeRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtrNoBlock loc !fd !buf !off !len
#if defined(javascript_HOST_ARCH)
= mask_ $ do
r <- throwErrnoIfMinus1 loc (c_write (fdFD fd) (buf `plusPtr` off) len)
case r of
(-1) -> return 0
n -> return (fromIntegral n)
#else
| isNonBlocking fd = unsafe_write
| otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0
if r /= 0 then write
else return 0
where
do_write call = do r <- throwErrnoIfMinus1RetryOnBlock loc call (return (-1))
case r of
(-1) -> return 0
n -> return (fromIntegral n)
write = if threaded then safe_write else unsafe_write
unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len)
safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)
#endif
#if !defined(javascript_HOST_ARCH)
isNonBlocking :: FD -> Bool
isNonBlocking fd = fdIsNonBlocking fd /= 0
foreign import ccall unsafe "fdReady"
unsafe_fdReady :: CInt -> CBool -> Int64 -> CBool -> IO CInt
#endif
#else /* mingw32_HOST_OS.... */
readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtr String
loc !FD
fd !Ptr Word8
buf !Int
off !CSize
len
| Bool
threaded = String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
blockingReadRawBufferPtr String
loc FD
fd Ptr Word8
buf Int
off CSize
len
| Bool
otherwise = String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
asyncReadRawBufferPtr String
loc FD
fd Ptr Word8
buf Int
off CSize
len
writeRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtr String
loc !FD
fd !Ptr Word8
buf !Int
off !CSize
len
| Bool
threaded = String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
blockingWriteRawBufferPtr String
loc FD
fd Ptr Word8
buf Int
off CSize
len
| Bool
otherwise = String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
asyncWriteRawBufferPtr String
loc FD
fd Ptr Word8
buf Int
off CSize
len
readRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtrNoBlock = String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtr
writeRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtrNoBlock = String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
writeRawBufferPtr
asyncReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
asyncReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
asyncReadRawBufferPtr String
loc !FD
fd !Ptr Word8
buf !Int
off !CSize
len = do
(l, rc) <- Int -> Int -> Int -> Ptr (ZonkAny 0) -> IO (Int, Int)
forall a. Int -> Int -> Int -> Ptr a -> IO (Int, Int)
asyncRead (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (FD -> CInt
fdFD FD
fd)) (FD -> Int
fdIsSocket_ FD
fd)
(CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len) (Ptr Word8
buf Ptr Word8 -> Int -> Ptr (ZonkAny 0)
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off)
if l == (-1)
then let sock_errno = Word32 -> Errno
c_maperrno_func (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
rc)
non_sock_errno = CInt -> Errno
Errno (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
rc)
errno = Errno -> Errno -> Bool -> Errno
forall a. a -> a -> Bool -> a
bool Errno
non_sock_errno Errno
sock_errno (FD -> Bool
fdIsSocket FD
fd)
in ioError (errnoToIOError loc errno Nothing Nothing)
else return (fromIntegral l)
asyncWriteRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
asyncWriteRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
asyncWriteRawBufferPtr String
loc !FD
fd !Ptr Word8
buf !Int
off !CSize
len = do
(l, rc) <- Int -> Int -> Int -> Ptr (ZonkAny 1) -> IO (Int, Int)
forall a. Int -> Int -> Int -> Ptr a -> IO (Int, Int)
asyncWrite (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (FD -> CInt
fdFD FD
fd)) (FD -> Int
fdIsSocket_ FD
fd)
(CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len) (Ptr Word8
buf Ptr Word8 -> Int -> Ptr (ZonkAny 1)
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off)
if l == (-1)
then let sock_errno = Word32 -> Errno
c_maperrno_func (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
rc)
non_sock_errno = CInt -> Errno
Errno (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
rc)
errno = Errno -> Errno -> Bool -> Errno
forall a. a -> a -> Bool -> a
bool Errno
non_sock_errno Errno
sock_errno (FD -> Bool
fdIsSocket FD
fd)
in ioError (errnoToIOError loc errno Nothing Nothing)
else return (fromIntegral l)
blockingReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
blockingReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
blockingReadRawBufferPtr String
loc !FD
fd !Ptr Word8
buf !Int
off !CSize
len
= String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
loc (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ do
let start_ptr :: Ptr b
start_ptr = Ptr Word8
buf Ptr Word8 -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off
recv_ret :: IO CInt
recv_ret = CInt -> Ptr Word8 -> CInt -> CInt -> IO CInt
c_safe_recv (FD -> CInt
fdFD FD
fd) Ptr Word8
forall {b}. Ptr b
start_ptr (CSize -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len) CInt
0
read_ret :: IO CInt
read_ret = CInt -> Ptr Word8 -> CUInt -> IO CInt
c_safe_read (FD -> CInt
fdFD FD
fd) Ptr Word8
forall {b}. Ptr b
start_ptr (CSize -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len)
r <- IO CInt -> IO CInt -> Bool -> IO CInt
forall a. a -> a -> Bool -> a
bool IO CInt
read_ret IO CInt
recv_ret (FD -> Bool
fdIsSocket FD
fd)
when ((fdIsSocket fd) && (r == -1)) c_maperrno
return r
blockingWriteRawBufferPtr :: String -> FD -> Ptr Word8-> Int -> CSize -> IO CInt
blockingWriteRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
blockingWriteRawBufferPtr String
loc !FD
fd !Ptr Word8
buf !Int
off !CSize
len
= String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
loc (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ do
let start_ptr :: Ptr b
start_ptr = Ptr Word8
buf Ptr Word8 -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off
send_ret :: IO CInt
send_ret = CInt -> Ptr Word8 -> CInt -> CInt -> IO CInt
c_safe_send (FD -> CInt
fdFD FD
fd) Ptr Word8
forall {b}. Ptr b
start_ptr (CSize -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len) CInt
0
write_ret :: IO CInt
write_ret = CInt -> Ptr Word8 -> CUInt -> IO CInt
c_safe_write (FD -> CInt
fdFD FD
fd) Ptr Word8
forall {b}. Ptr b
start_ptr (CSize -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len)
r <- IO CInt -> IO CInt -> Bool -> IO CInt
forall a. a -> a -> Bool -> a
bool IO CInt
write_ret IO CInt
send_ret (FD -> Bool
fdIsSocket FD
fd)
when (r == -1) c_maperrno
return r
foreign import ccall safe "recv"
c_safe_recv :: CInt -> Ptr Word8 -> CInt -> CInt -> IO CInt
foreign import ccall safe "send"
c_safe_send :: CInt -> Ptr Word8 -> CInt -> CInt -> IO CInt
#endif
#if !defined(javascript_HOST_ARCH)
foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool
#endif
#if !defined(mingw32_HOST_OS) && !defined(javascript_HOST_ARCH)
throwErrnoIfMinus1RetryOnBlock :: String -> IO CSsize -> IO CSsize -> IO CSsize
throwErrnoIfMinus1RetryOnBlock loc f on_block =
do
res <- f
if (res :: CSsize) == -1
then do
err <- getErrno
if err == eINTR
then throwErrnoIfMinus1RetryOnBlock loc f on_block
else if err == eWOULDBLOCK || err == eAGAIN
then on_block
else throwErrno loc
else return res
#endif
foreign import ccall unsafe "lockFile"
lockFile :: Word64 -> Word64 -> Word64 -> CInt -> IO CInt
foreign import ccall unsafe "unlockFile"
unlockFile :: Word64 -> IO CInt
#if defined(mingw32_HOST_OS)
foreign import ccall unsafe "get_unique_file_info"
c_getUniqueFileInfo :: CInt -> Ptr Word64 -> Ptr Word64 -> IO ()
#endif