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