{-# LANGUAGE Trustworthy #-}{-# LANGUAGE InterruptibleFFI #-}{-# LANGUAGE CPP, NoImplicitPrelude, CApiFFI #-}{-# LANGUAGE LambdaCase #-}{-# LANGUAGE UnboxedTuples #-}{-# LANGUAGE MagicHash #-}{-# OPTIONS_HADDOCK not-home #-}------------------------------------------------------------------------------- |-- Module : System.Posix.Internals-- Copyright : (c) The University of Glasgow, 1992-2002-- License : see libraries/base/LICENSE---- Maintainer : cvs-ghc@haskell.org-- Stability : internal-- Portability : non-portable (requires POSIX)---- POSIX support layer for the standard libraries.-- This library is built on *every* platform, including Win32.---- Non-posix compliant in order to support the following features:-- * S_ISSOCK (no sockets in POSIX)-------------------------------------------------------------------------------moduleSystem.Posix.Internalswhere
#include "HsBaseConfig.h"
importSystem.Posix.Types importForeign importForeign.C -- import Data.BitsimportData.Maybe 
#if !defined(HTYPE_TCFLAG_T)
importSystem.IO.Error
#endif
importGHC.Base importGHC.Num importGHC.Real importGHC.IO importGHC.IO.IOMode importGHC.IO.Exception importGHC.IO.Device 
#if !defined(mingw32_HOST_OS)
import{-# SOURCE#-}GHC.IO.Encoding (getFileSystemEncoding )importqualifiedGHC.Foreign asGHC
#endif
-- ----------------------------------------------------------------------------- Debugging the base packageputs ::String ->IO ()puts :: String -> IO ()
puts String
s =forall a. String -> (CStringLen -> IO a) -> IO a
withCAStringLen (String
s forall a. [a] -> [a] -> [a]
++ String
"\n")forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
p ,Int
len )->do-- In reality should be withCString, but assume ASCII to avoid loop-- if this is called by GHC.ForeignCSsize
_<-CInt -> Ptr Word8 -> CSize -> IO CSsize
c_write CInt
1(forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
p )(forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len )forall (m :: * -> *) a. Monad m => a -> m a
return ()-- ----------------------------------------------------------------------------- Typesdata{-# CTYPE"struct flock"#-}CFLock data{-# CTYPE"struct group"#-}CGroup data{-# CTYPE"struct lconv"#-}CLconv data{-# CTYPE"struct passwd"#-}CPasswd data{-# CTYPE"struct sigaction"#-}CSigaction data{-# CTYPE"sigset_t"#-}CSigset data{-# CTYPE"struct stat"#-}CStat data{-# CTYPE"struct termios"#-}CTermios data{-# CTYPE"struct tm"#-}CTm data{-# CTYPE"struct tms"#-}CTms data{-# CTYPE"struct utimbuf"#-}CUtimbuf data{-# CTYPE"struct utsname"#-}CUtsname typeFD =CInt -- ----------------------------------------------------------------------------- stat()-related stufffdFileSize ::FD ->IO Integer fdFileSize :: CInt -> IO Integer
fdFileSize CInt
fd =forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
sizeof_stat forall a b. (a -> b) -> a -> b
$ \Ptr CStat
p_stat ->doforall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_ String
"fileSize"forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CStat -> IO CInt
c_fstat CInt
fd Ptr CStat
p_stat CMode
c_mode <-Ptr CStat -> IO CMode
st_mode Ptr CStat
p_stat ::IO CMode ifBool -> Bool
not (CMode -> Bool
s_isreg CMode
c_mode )thenforall (m :: * -> *) a. Monad m => a -> m a
return (-Integer
1)elsedoCOff
c_size <-Ptr CStat -> IO COff
st_size Ptr CStat
p_stat forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. (Integral a, Num b) => a -> b
fromIntegral COff
c_size )fileType ::FilePath ->IO IODeviceType fileType :: String -> IO IODeviceType
fileType String
file =forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
sizeof_stat forall a b. (a -> b) -> a -> b
$ \Ptr CStat
p_stat ->forall a. String -> (Ptr CChar -> IO a) -> IO a
withFilePath String
file forall a b. (a -> b) -> a -> b
$ \Ptr CChar
p_file ->doforall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_ String
"fileType"forall a b. (a -> b) -> a -> b
$ Ptr CChar -> Ptr CStat -> IO CInt
c_stat Ptr CChar
p_file Ptr CStat
p_stat Ptr CStat -> IO IODeviceType
statGetType Ptr CStat
p_stat -- NOTE: On Win32 platforms, this will only work with file descriptors-- referring to file handles. i.e., it'll fail for socket FDs.fdStat ::FD ->IO (IODeviceType ,CDev ,CIno )fdStat :: CInt -> IO (IODeviceType, CDev, CIno)
fdStat CInt
fd =forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
sizeof_stat forall a b. (a -> b) -> a -> b
$ \Ptr CStat
p_stat ->doforall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_ String
"fdType"forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CStat -> IO CInt
c_fstat CInt
fd Ptr CStat
p_stat IODeviceType
ty <-Ptr CStat -> IO IODeviceType
statGetType Ptr CStat
p_stat CDev
dev <-Ptr CStat -> IO CDev
st_dev Ptr CStat
p_stat CIno
ino <-Ptr CStat -> IO CIno
st_ino Ptr CStat
p_stat forall (m :: * -> *) a. Monad m => a -> m a
return (IODeviceType
ty ,CDev
dev ,CIno
ino )fdType ::FD ->IO IODeviceType fdType :: CInt -> IO IODeviceType
fdType CInt
fd =do(IODeviceType
ty ,CDev
_,CIno
_)<-CInt -> IO (IODeviceType, CDev, CIno)
fdStat CInt
fd ;forall (m :: * -> *) a. Monad m => a -> m a
return IODeviceType
ty statGetType ::Ptr CStat ->IO IODeviceType statGetType :: Ptr CStat -> IO IODeviceType
statGetType Ptr CStat
p_stat =doCMode
c_mode <-Ptr CStat -> IO CMode
st_mode Ptr CStat
p_stat ::IO CMode case()of()
_|CMode -> Bool
s_isdir CMode
c_mode ->forall (m :: * -> *) a. Monad m => a -> m a
return IODeviceType
Directory |CMode -> Bool
s_isfifo CMode
c_mode Bool -> Bool -> Bool
|| CMode -> Bool
s_issock CMode
c_mode Bool -> Bool -> Bool
|| CMode -> Bool
s_ischr CMode
c_mode ->forall (m :: * -> *) a. Monad m => a -> m a
return IODeviceType
Stream |CMode -> Bool
s_isreg CMode
c_mode ->forall (m :: * -> *) a. Monad m => a -> m a
return IODeviceType
RegularFile -- Q: map char devices to RawDevice too?|CMode -> Bool
s_isblk CMode
c_mode ->forall (m :: * -> *) a. Monad m => a -> m a
return IODeviceType
RawDevice |Bool
otherwise ->forall a. IOError -> IO a
ioError IOError
ioe_unknownfiletype ioe_unknownfiletype ::IOException ioe_unknownfiletype :: IOError
ioe_unknownfiletype =Maybe Handle
-> IOErrorType
-> String
-> String
-> Maybe CInt
-> Maybe String
-> IOError
IOError forall a. Maybe a
Nothing IOErrorType
UnsupportedOperation String
"fdType"String
"unknown file type"forall a. Maybe a
Nothing forall a. Maybe a
Nothing fdGetMode ::FD ->IO IOMode 
#if defined(mingw32_HOST_OS)
fdGetMode_=do-- We don't have a way of finding out which flags are set on FDs-- on Windows, so make a handle that thinks that anything goes.letflags=o_RDWR
#else
fdGetMode :: CInt -> IO IOMode
fdGetMode CInt
fd =doCInt
flags <-forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
"fdGetMode"(CInt -> CInt -> IO CInt
c_fcntl_read CInt
fd CInt
const_f_getfl )
#endif
letwH :: Bool
wH =(CInt
flags forall a. Bits a => a -> a -> a
.&. CInt
o_WRONLY )forall a. Eq a => a -> a -> Bool
/= CInt
0aH :: Bool
aH =(CInt
flags forall a. Bits a => a -> a -> a
.&. CInt
o_APPEND )forall a. Eq a => a -> a -> Bool
/= CInt
0rwH :: Bool
rwH =(CInt
flags forall a. Bits a => a -> a -> a
.&. CInt
o_RDWR )forall a. Eq a => a -> a -> Bool
/= CInt
0mode :: IOMode
mode |Bool
wH Bool -> Bool -> Bool
&& Bool
aH =IOMode
AppendMode |Bool
wH =IOMode
WriteMode |Bool
rwH =IOMode
ReadWriteMode |Bool
otherwise =IOMode
ReadMode forall (m :: * -> *) a. Monad m => a -> m a
return IOMode
mode 
#if defined(mingw32_HOST_OS)
withFilePath::FilePath->(CWString->IOa)->IOawithFilePath=withCWStringnewFilePath::FilePath->IOCWStringnewFilePath=newCWStringpeekFilePath::CWString->IOFilePathpeekFilePath=peekCWString
#else
withFilePath ::FilePath ->(CString ->IO a )->IO a newFilePath ::FilePath ->IO CString peekFilePath ::CString ->IO FilePath peekFilePathLen ::CStringLen ->IO FilePath withFilePath :: forall a. String -> (Ptr CChar -> IO a) -> IO a
withFilePath String
fp Ptr CChar -> IO a
f =IO TextEncoding
getFileSystemEncoding forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \TextEncoding
enc ->forall a. TextEncoding -> String -> (Ptr CChar -> IO a) -> IO a
GHC.withCString TextEncoding
enc String
fp Ptr CChar -> IO a
f newFilePath :: String -> IO (Ptr CChar)
newFilePath String
fp =IO TextEncoding
getFileSystemEncoding forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \TextEncoding
enc ->TextEncoding -> String -> IO (Ptr CChar)
GHC.newCString TextEncoding
enc String
fp peekFilePath :: Ptr CChar -> IO String
peekFilePath Ptr CChar
fp =IO TextEncoding
getFileSystemEncoding forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \TextEncoding
enc ->TextEncoding -> Ptr CChar -> IO String
GHC.peekCString TextEncoding
enc Ptr CChar
fp peekFilePathLen :: CStringLen -> IO String
peekFilePathLen CStringLen
fp =IO TextEncoding
getFileSystemEncoding forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \TextEncoding
enc ->TextEncoding -> CStringLen -> IO String
GHC.peekCStringLen TextEncoding
enc CStringLen
fp 
#endif
-- ----------------------------------------------------------------------------- Terminal-related stuff
#if defined(HTYPE_TCFLAG_T)
setEcho ::FD ->Bool ->IO ()setEcho :: CInt -> Bool -> IO ()
setEcho CInt
fd Bool
on =forall a. CInt -> (Ptr CTermios -> IO a) -> IO a
tcSetAttr CInt
fd forall a b. (a -> b) -> a -> b
$ \Ptr CTermios
p_tios ->doCTcflag
lflag <-Ptr CTermios -> IO CTcflag
c_lflag Ptr CTermios
p_tios ::IO CTcflag letnew_lflag :: CTcflag
new_lflag |Bool
on =CTcflag
lflag forall a. Bits a => a -> a -> a
.|. forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
const_echo |Bool
otherwise =CTcflag
lflag forall a. Bits a => a -> a -> a
.&. forall a. Bits a => a -> a
complement (forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
const_echo )Ptr CTermios -> CTcflag -> IO ()
poke_c_lflag Ptr CTermios
p_tios (CTcflag
new_lflag ::CTcflag )getEcho ::FD ->IO Bool getEcho :: CInt -> IO Bool
getEcho CInt
fd =forall a. CInt -> (Ptr CTermios -> IO a) -> IO a
tcSetAttr CInt
fd forall a b. (a -> b) -> a -> b
$ \Ptr CTermios
p_tios ->doCTcflag
lflag <-Ptr CTermios -> IO CTcflag
c_lflag Ptr CTermios
p_tios ::IO CTcflag forall (m :: * -> *) a. Monad m => a -> m a
return ((CTcflag
lflag forall a. Bits a => a -> a -> a
.&. forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
const_echo )forall a. Eq a => a -> a -> Bool
/= CTcflag
0)setCooked ::FD ->Bool ->IO ()setCooked :: CInt -> Bool -> IO ()
setCooked CInt
fd Bool
cooked =forall a. CInt -> (Ptr CTermios -> IO a) -> IO a
tcSetAttr CInt
fd forall a b. (a -> b) -> a -> b
$ \Ptr CTermios
p_tios ->do-- turn on/off ICANONCTcflag
lflag <-Ptr CTermios -> IO CTcflag
c_lflag Ptr CTermios
p_tios ::IO CTcflag letnew_lflag :: CTcflag
new_lflag |Bool
cooked =CTcflag
lflag forall a. Bits a => a -> a -> a
.|. (forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
const_icanon )|Bool
otherwise =CTcflag
lflag forall a. Bits a => a -> a -> a
.&. forall a. Bits a => a -> a
complement (forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
const_icanon )Ptr CTermios -> CTcflag -> IO ()
poke_c_lflag Ptr CTermios
p_tios (CTcflag
new_lflag ::CTcflag )-- set VMIN & VTIME to 1/0 respectivelyforall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
cooked )forall a b. (a -> b) -> a -> b
$ doPtr Word8
c_cc <-Ptr CTermios -> IO (Ptr Word8)
ptr_c_cc Ptr CTermios
p_tios letvmin :: Ptr Word8
vmin =(Ptr Word8
c_cc forall a b. Ptr a -> Int -> Ptr b
`plusPtr` (forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
const_vmin ))::Ptr Word8 vtime :: Ptr Word8
vtime =(Ptr Word8
c_cc forall a b. Ptr a -> Int -> Ptr b
`plusPtr` (forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
const_vtime ))::Ptr Word8 forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
vmin Word8
1forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
vtime Word8
0tcSetAttr ::FD ->(Ptr CTermios ->IO a )->IO a tcSetAttr :: forall a. CInt -> (Ptr CTermios -> IO a) -> IO a
tcSetAttr CInt
fd Ptr CTermios -> IO a
fun =forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
sizeof_termios forall a b. (a -> b) -> a -> b
$ \Ptr CTermios
p_tios ->doforall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_ String
"tcSetAttr"(CInt -> Ptr CTermios -> IO CInt
c_tcgetattr CInt
fd Ptr CTermios
p_tios )-- Save a copy of termios, if this is a standard file descriptor.-- These terminal settings are restored in hs_exit().forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
fd forall a. Ord a => a -> a -> Bool
<= CInt
2)forall a b. (a -> b) -> a -> b
$ doPtr CTermios
p <-CInt -> IO (Ptr CTermios)
get_saved_termios CInt
fd forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Ptr CTermios
p forall a. Eq a => a -> a -> Bool
== forall a. Ptr a
nullPtr )forall a b. (a -> b) -> a -> b
$ doPtr CTermios
saved_tios <-forall a. Int -> IO (Ptr a)
mallocBytes Int
sizeof_termios forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr CTermios
saved_tios Ptr CTermios
p_tios Int
sizeof_termios CInt -> Ptr CTermios -> IO ()
set_saved_termios CInt
fd Ptr CTermios
saved_tios -- tcsetattr() when invoked by a background process causes the process-- to be sent SIGTTOU regardless of whether the process has TOSTOP set-- in its terminal flags (try it...). This function provides a-- wrapper which temporarily blocks SIGTTOU around the call, making it-- transparent.forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
sizeof_sigset_t forall a b. (a -> b) -> a -> b
$ \Ptr CSigset
p_sigset ->forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
sizeof_sigset_t forall a b. (a -> b) -> a -> b
$ \Ptr CSigset
p_old_sigset ->doforall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1_ String
"sigemptyset"forall a b. (a -> b) -> a -> b
$ Ptr CSigset -> IO CInt
c_sigemptyset Ptr CSigset
p_sigset forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1_ String
"sigaddset"forall a b. (a -> b) -> a -> b
$ Ptr CSigset -> CInt -> IO CInt
c_sigaddset Ptr CSigset
p_sigset CInt
const_sigttou forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1_ String
"sigprocmask"forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CSigset -> Ptr CSigset -> IO CInt
c_sigprocmask CInt
const_sig_block Ptr CSigset
p_sigset Ptr CSigset
p_old_sigset a
r <-Ptr CTermios -> IO a
fun Ptr CTermios
p_tios -- do the businessforall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_ String
"tcSetAttr"forall a b. (a -> b) -> a -> b
$ CInt -> CInt -> Ptr CTermios -> IO CInt
c_tcsetattr CInt
fd CInt
const_tcsanow Ptr CTermios
p_tios forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1_ String
"sigprocmask"forall a b. (a -> b) -> a -> b
$ CInt -> Ptr CSigset -> Ptr CSigset -> IO CInt
c_sigprocmask CInt
const_sig_setmask Ptr CSigset
p_old_sigset forall a. Ptr a
nullPtr forall (m :: * -> *) a. Monad m => a -> m a
return a
r foreignimportccallunsafe"HsBase.h __hscore_get_saved_termios"get_saved_termios ::CInt ->IO (Ptr CTermios )foreignimportccallunsafe"HsBase.h __hscore_set_saved_termios"set_saved_termios ::CInt ->(Ptr CTermios )->IO ()
#else
-- 'raw' mode for Win32 means turn off 'line input' (=> buffering and-- character translation for the console.) The Win32 API for doing-- this is GetConsoleMode(), which also requires echoing to be disabled-- when turning off 'line input' processing. Notice that turning off-- 'line input' implies enter/return is reported as '\r' (and it won't-- report that character until another character is input..odd.) This-- latter feature doesn't sit too well with IO actions like IO.hGetLine..-- consider yourself warned.setCooked::FD->Bool->IO()setCookedfdcooked=dox<-set_console_bufferingfd(ifcookedthen1else0)if(x/=0)thenioError(ioe_unk_error"setCooked""failed to set buffering")elsereturn()ioe_unk_error::String->String->IOExceptionioe_unk_errorlocmsg=ioeSetErrorString(mkIOErrorOtherErrorlocNothingNothing)msg-- Note: echoing goes hand in hand with enabling 'line input' / raw-ness-- for Win32 consoles, hence setEcho ends up being the inverse of setCooked.setEcho::FD->Bool->IO()setEchofdon=dox<-set_console_echofd(ifonthen1else0)if(x/=0)thenioError(ioe_unk_error"setEcho""failed to set echoing")elsereturn()getEcho::FD->IOBoolgetEchofd=dor<-get_console_echofdif(r==(-1))thenioError(ioe_unk_error"getEcho""failed to get echoing")elsereturn(r==1)foreignimportccallunsafe"consUtils.h set_console_buffering__"set_console_buffering::CInt->CInt->IOCIntforeignimportccallunsafe"consUtils.h set_console_echo__"set_console_echo::CInt->CInt->IOCIntforeignimportccallunsafe"consUtils.h get_console_echo__"get_console_echo::CInt->IOCIntforeignimportccallunsafe"consUtils.h is_console__"is_console::CInt->IOCInt
#endif
-- ----------------------------------------------------------------------------- Turning on non-blocking for a file descriptorsetNonBlockingFD ::FD ->Bool ->IO ()
#if !defined(mingw32_HOST_OS)
setNonBlockingFD :: CInt -> Bool -> IO ()
setNonBlockingFD CInt
fd Bool
set =doCInt
flags <-forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry String
"setNonBlockingFD"(CInt -> CInt -> IO CInt
c_fcntl_read CInt
fd CInt
const_f_getfl )letflags' :: CInt
flags' |Bool
set =CInt
flags forall a. Bits a => a -> a -> a
.|. CInt
o_NONBLOCK |Bool
otherwise =CInt
flags forall a. Bits a => a -> a -> a
.&. forall a. Bits a => a -> a
complement CInt
o_NONBLOCK forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
flags forall a. Eq a => a -> a -> Bool
/= CInt
flags' )forall a b. (a -> b) -> a -> b
$ do-- An error when setting O_NONBLOCK isn't fatal: on some systems-- there are certain file handles on which this will fail (eg. /dev/null-- on FreeBSD) so we throw away the return code from fcntl_write.CInt
_<-CInt -> CInt -> CLong -> IO CInt
c_fcntl_write CInt
fd CInt
const_f_setfl (forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
flags' )forall (m :: * -> *) a. Monad m => a -> m a
return ()
#else
-- bogus defns for win32setNonBlockingFD__=return()
#endif
-- ------------------------------------------------------------------------------- Set close-on-exec for a file descriptor
#if !defined(mingw32_HOST_OS)
setCloseOnExec ::FD ->IO ()setCloseOnExec :: CInt -> IO ()
setCloseOnExec CInt
fd =forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1_ String
"setCloseOnExec"forall a b. (a -> b) -> a -> b
$ CInt -> CInt -> CLong -> IO CInt
c_fcntl_write CInt
fd CInt
const_f_setfd CLong
const_fd_cloexec 
#endif
-- ------------------------------------------------------------------------------- foreign imports
#if !defined(mingw32_HOST_OS)
typeCFilePath =CString 
#else
typeCFilePath=CWString
#endif
foreignimportccallunsafe"HsBase.h __hscore_open"c_open ::CFilePath ->CInt ->CMode ->IO CInt -- | The same as 'c_safe_open', but an /interruptible operation/-- as described in "Control.Exception"—it respects `uninterruptibleMask`-- but not `mask`.---- We want to be able to interrupt an openFile call if-- it's expensive (NFS, FUSE, etc.), and we especially-- need to be able to interrupt a blocking open call.-- See #17912.c_interruptible_open ::CFilePath ->CInt ->CMode ->IO CInt c_interruptible_open :: Ptr CChar -> CInt -> CMode -> IO CInt
c_interruptible_open Ptr CChar
filepath CInt
oflags CMode
mode =IO MaskingState
getMaskingState forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case-- If we're in an uninterruptible mask, there's basically-- no point in using an interruptible FFI call. The open system call-- will be interrupted, but the exception won't be delivered-- unless the caller manually futzes with the masking state. So-- then the caller (assuming they're following the usual conventions)-- will retry the call (in response to EINTR), and we've just-- wasted everyone's time.MaskingState
MaskedUninterruptible ->Ptr CChar -> CInt -> CMode -> IO CInt
c_safe_open_ Ptr CChar
filepath CInt
oflags CMode
mode MaskingState
_->doCInt
open_res <-Ptr CChar -> CInt -> CMode -> IO CInt
c_interruptible_open_ Ptr CChar
filepath CInt
oflags CMode
mode -- c_interruptible_open_ is an interruptible foreign call.-- If the call is interrupted by an exception handler-- before the system call has returned (so the file is-- not yet open), we want to deliver the exception.-- In point of fact, we deliver any pending exception-- here regardless of the *reason* the system call-- fails.forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
open_res forall a. Eq a => a -> a -> Bool
== -CInt
1)forall a b. (a -> b) -> a -> b
$ ifBool
hostIsThreaded then-- Control.Exception.allowInterrupt, inlined to avoid-- messing with any Haddock links.forall a. IO a -> IO a
interruptible (forall (f :: * -> *) a. Applicative f => a -> f a
pure ())else-- Try to make this work somewhat better on the non-threaded-- RTS. See #8684. This inlines the definition of `yield`; module-- dependencies look pretty hairy here and I don't want to make-- things worse for one little wrapper.forall a. IO a -> IO a
interruptible (forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s ->(#State# RealWorld -> State# RealWorld
yield# State# RealWorld
s ,()#))forall (f :: * -> *) a. Applicative f => a -> f a
pure CInt
open_res foreignimportccallinterruptible"HsBase.h __hscore_open"c_interruptible_open_ ::CFilePath ->CInt ->CMode ->IO CInt -- | Consult the RTS to find whether it is threaded.hostIsThreaded ::Bool hostIsThreaded :: Bool
hostIsThreaded =Int
rtsIsThreaded_ forall a. Eq a => a -> a -> Bool
/= Int
0foreignimportccallunsafe"rts_isThreaded"rtsIsThreaded_ ::Int c_safe_open ::CFilePath ->CInt ->CMode ->IO CInt c_safe_open :: Ptr CChar -> CInt -> CMode -> IO CInt
c_safe_open Ptr CChar
filepath CInt
oflags CMode
mode =IO MaskingState
getMaskingState forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case-- When exceptions are unmasked, we use an interruptible-- open call. If the system call is successfully-- interrupted, the situation will be the same as if-- the exception had arrived before this function was-- called.MaskingState
Unmasked ->Ptr CChar -> CInt -> CMode -> IO CInt
c_interruptible_open_ Ptr CChar
filepath CInt
oflags CMode
mode MaskingState
_->Ptr CChar -> CInt -> CMode -> IO CInt
c_safe_open_ Ptr CChar
filepath CInt
oflags CMode
mode foreignimportccallsafe"HsBase.h __hscore_open"c_safe_open_ ::CFilePath ->CInt ->CMode ->IO CInt foreignimportccallunsafe"HsBase.h __hscore_fstat"c_fstat ::CInt ->Ptr CStat ->IO CInt foreignimportccallunsafe"HsBase.h __hscore_lstat"lstat ::CFilePath ->Ptr CStat ->IO CInt {- Note: Win32 POSIX functions
Functions that are not part of the POSIX standards were
at some point deprecated by Microsoft. This deprecation
was performed by renaming the functions according to the
C++ ABI Section 17.6.4.3.2b. This was done to free up the
namespace of normal Windows programs since Windows isn't
POSIX compliant anyway.
These were working before since the RTS was re-exporting
these symbols under the undeprecated names. This is no longer
being done. See #11223
See https://msdn.microsoft.com/en-us/library/ms235384.aspx
for more.
However since we can't hope to get people to support Windows
packages we should support the deprecated names. See #12497
-}foreignimportcapiunsafe"unistd.h lseek"c_lseek ::CInt ->COff ->CInt ->IO COff foreignimportccallunsafe"HsBase.h access"c_access ::CString ->CInt ->IO CInt foreignimportccallunsafe"HsBase.h chmod"c_chmod ::CString ->CMode ->IO CInt foreignimportccallunsafe"HsBase.h close"c_close ::CInt ->IO CInt foreignimportccallunsafe"HsBase.h creat"c_creat ::CString ->CMode ->IO CInt foreignimportccallunsafe"HsBase.h dup"c_dup ::CInt ->IO CInt foreignimportccallunsafe"HsBase.h dup2"c_dup2 ::CInt ->CInt ->IO CInt foreignimportccallunsafe"HsBase.h isatty"c_isatty ::CInt ->IO CInt 
#if defined(mingw32_HOST_OS)
-- See Note: Windows typesforeignimportcapiunsafe"HsBase.h _read"c_read::CInt->PtrWord8->CUInt->IOCInt-- See Note: Windows typesforeignimportcapisafe"HsBase.h _read"c_safe_read::CInt->PtrWord8->CUInt->IOCIntforeignimportccallunsafe"HsBase.h _umask"c_umask::CMode->IOCMode-- See Note: Windows typesforeignimportcapiunsafe"HsBase.h _write"c_write::CInt->PtrWord8->CUInt->IOCInt-- See Note: Windows typesforeignimportcapisafe"HsBase.h _write"c_safe_write::CInt->PtrWord8->CUInt->IOCIntforeignimportccallunsafe"HsBase.h _pipe"c_pipe::PtrCInt->IOCInt
#else
-- We use CAPI as on some OSs (eg. Linux) this is wrapped by a macro-- which redirects to the 64-bit-off_t versions when large file-- support is enabled.-- See Note: Windows typesforeignimportcapiunsafe"HsBase.h read"c_read ::CInt ->Ptr Word8 ->CSize ->IO CSsize -- See Note: Windows typesforeignimportcapisafe"HsBase.h read"c_safe_read ::CInt ->Ptr Word8 ->CSize ->IO CSsize foreignimportccallunsafe"HsBase.h umask"c_umask ::CMode ->IO CMode -- See Note: Windows typesforeignimportcapiunsafe"HsBase.h write"c_write ::CInt ->Ptr Word8 ->CSize ->IO CSsize -- See Note: Windows typesforeignimportcapisafe"HsBase.h write"c_safe_write ::CInt ->Ptr Word8 ->CSize ->IO CSsize foreignimportccallunsafe"HsBase.h pipe"c_pipe ::Ptr CInt ->IO CInt 
#endif
foreignimportccallunsafe"HsBase.h unlink"c_unlink ::CString ->IO CInt foreignimportcapiunsafe"HsBase.h utime"c_utime ::CString ->Ptr CUtimbuf ->IO CInt foreignimportccallunsafe"HsBase.h getpid"c_getpid ::IO CPid foreignimportccallunsafe"HsBase.h __hscore_stat"c_stat ::CFilePath ->Ptr CStat ->IO CInt foreignimportccallunsafe"HsBase.h __hscore_ftruncate"c_ftruncate ::CInt ->COff ->IO CInt 
#if !defined(mingw32_HOST_OS)
foreignimportcapiunsafe"HsBase.h fcntl"c_fcntl_read ::CInt ->CInt ->IO CInt foreignimportcapiunsafe"HsBase.h fcntl"c_fcntl_write ::CInt ->CInt ->CLong ->IO CInt foreignimportcapiunsafe"HsBase.h fcntl"c_fcntl_lock ::CInt ->CInt ->Ptr CFLock ->IO CInt foreignimportccallunsafe"HsBase.h fork"c_fork ::IO CPid foreignimportccallunsafe"HsBase.h link"c_link ::CString ->CString ->IO CInt -- capi is required at least on Androidforeignimportcapiunsafe"HsBase.h mkfifo"c_mkfifo ::CString ->CMode ->IO CInt foreignimportcapiunsafe"signal.h sigemptyset"c_sigemptyset ::Ptr CSigset ->IO CInt foreignimportcapiunsafe"signal.h sigaddset"c_sigaddset ::Ptr CSigset ->CInt ->IO CInt foreignimportcapiunsafe"signal.h sigprocmask"c_sigprocmask ::CInt ->Ptr CSigset ->Ptr CSigset ->IO CInt -- capi is required at least on Androidforeignimportcapiunsafe"HsBase.h tcgetattr"c_tcgetattr ::CInt ->Ptr CTermios ->IO CInt -- capi is required at least on Androidforeignimportcapiunsafe"HsBase.h tcsetattr"c_tcsetattr ::CInt ->CInt ->Ptr CTermios ->IO CInt foreignimportccallunsafe"HsBase.h waitpid"c_waitpid ::CPid ->Ptr CInt ->CInt ->IO CPid 
#endif
-- POSIX flags only:foreignimportccallunsafe"HsBase.h __hscore_o_rdonly"o_RDONLY ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_wronly"o_WRONLY ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_rdwr"o_RDWR ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_append"o_APPEND ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_creat"o_CREAT ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_excl"o_EXCL ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_trunc"o_TRUNC ::CInt -- non-POSIX flags.foreignimportccallunsafe"HsBase.h __hscore_o_noctty"o_NOCTTY ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_nonblock"o_NONBLOCK ::CInt foreignimportccallunsafe"HsBase.h __hscore_o_binary"o_BINARY ::CInt foreignimportcapiunsafe"sys/stat.h S_ISREG"c_s_isreg ::CMode ->CInt foreignimportcapiunsafe"sys/stat.h S_ISCHR"c_s_ischr ::CMode ->CInt foreignimportcapiunsafe"sys/stat.h S_ISBLK"c_s_isblk ::CMode ->CInt foreignimportcapiunsafe"sys/stat.h S_ISDIR"c_s_isdir ::CMode ->CInt foreignimportcapiunsafe"sys/stat.h S_ISFIFO"c_s_isfifo ::CMode ->CInt s_isreg ::CMode ->Bool s_isreg :: CMode -> Bool
s_isreg CMode
cm =CMode -> CInt
c_s_isreg CMode
cm forall a. Eq a => a -> a -> Bool
/= CInt
0s_ischr ::CMode ->Bool s_ischr :: CMode -> Bool
s_ischr CMode
cm =CMode -> CInt
c_s_ischr CMode
cm forall a. Eq a => a -> a -> Bool
/= CInt
0s_isblk ::CMode ->Bool s_isblk :: CMode -> Bool
s_isblk CMode
cm =CMode -> CInt
c_s_isblk CMode
cm forall a. Eq a => a -> a -> Bool
/= CInt
0s_isdir ::CMode ->Bool s_isdir :: CMode -> Bool
s_isdir CMode
cm =CMode -> CInt
c_s_isdir CMode
cm forall a. Eq a => a -> a -> Bool
/= CInt
0s_isfifo ::CMode ->Bool s_isfifo :: CMode -> Bool
s_isfifo CMode
cm =CMode -> CInt
c_s_isfifo CMode
cm forall a. Eq a => a -> a -> Bool
/= CInt
0foreignimportccallunsafe"HsBase.h __hscore_sizeof_stat"sizeof_stat ::Int foreignimportccallunsafe"HsBase.h __hscore_st_mtime"st_mtime ::Ptr CStat ->IO CTime 
#if defined(mingw32_HOST_OS)
foreignimportccallunsafe"HsBase.h __hscore_st_size"st_size::PtrCStat->IOInt64
#else
foreignimportccallunsafe"HsBase.h __hscore_st_size"st_size ::Ptr CStat ->IO COff 
#endif
foreignimportccallunsafe"HsBase.h __hscore_st_mode"st_mode ::Ptr CStat ->IO CMode foreignimportccallunsafe"HsBase.h __hscore_st_dev"st_dev ::Ptr CStat ->IO CDev foreignimportccallunsafe"HsBase.h __hscore_st_ino"st_ino ::Ptr CStat ->IO CIno foreignimportccallunsafe"HsBase.h __hscore_echo"const_echo ::CInt foreignimportccallunsafe"HsBase.h __hscore_tcsanow"const_tcsanow ::CInt foreignimportccallunsafe"HsBase.h __hscore_icanon"const_icanon ::CInt foreignimportccallunsafe"HsBase.h __hscore_vmin"const_vmin ::CInt foreignimportccallunsafe"HsBase.h __hscore_vtime"const_vtime ::CInt foreignimportccallunsafe"HsBase.h __hscore_sigttou"const_sigttou ::CInt foreignimportccallunsafe"HsBase.h __hscore_sig_block"const_sig_block ::CInt foreignimportccallunsafe"HsBase.h __hscore_sig_setmask"const_sig_setmask ::CInt foreignimportccallunsafe"HsBase.h __hscore_f_getfl"const_f_getfl ::CInt foreignimportccallunsafe"HsBase.h __hscore_f_setfl"const_f_setfl ::CInt foreignimportccallunsafe"HsBase.h __hscore_f_setfd"const_f_setfd ::CInt foreignimportccallunsafe"HsBase.h __hscore_fd_cloexec"const_fd_cloexec ::CLong 
#if defined(HTYPE_TCFLAG_T)
foreignimportccallunsafe"HsBase.h __hscore_sizeof_termios"sizeof_termios ::Int foreignimportccallunsafe"HsBase.h __hscore_sizeof_sigset_t"sizeof_sigset_t ::Int foreignimportccallunsafe"HsBase.h __hscore_lflag"c_lflag ::Ptr CTermios ->IO CTcflag foreignimportccallunsafe"HsBase.h __hscore_poke_lflag"poke_c_lflag ::Ptr CTermios ->CTcflag ->IO ()foreignimportccallunsafe"HsBase.h __hscore_ptr_c_cc"ptr_c_cc ::Ptr CTermios ->IO (Ptr Word8 )
#endif
s_issock ::CMode ->Bool 
#if !defined(mingw32_HOST_OS)
s_issock :: CMode -> Bool
s_issock CMode
cmode =CMode -> CInt
c_s_issock CMode
cmode forall a. Eq a => a -> a -> Bool
/= CInt
0foreignimportcapiunsafe"sys/stat.h S_ISSOCK"c_s_issock ::CMode ->CInt 
#else
s_issock_=False
#endif
foreignimportccallunsafe"__hscore_bufsiz"dEFAULT_BUFFER_SIZE ::Int foreignimportcapiunsafe"stdio.h value SEEK_CUR"sEEK_CUR ::CInt foreignimportcapiunsafe"stdio.h value SEEK_SET"sEEK_SET ::CInt foreignimportcapiunsafe"stdio.h value SEEK_END"sEEK_END ::CInt {-
Note: Windows types
Windows' _read and _write have types that differ from POSIX. They take an
unsigned int for length and return a signed int where POSIX uses size_t and
ssize_t. Those are different on x86_64 and equivalent on x86. We import them
with the types in Microsoft's documentation which means that c_read,
c_safe_read, c_write and c_safe_write have different Haskell types depending on
the OS.
-}

AltStyle によって変換されたページ (->オリジナル) /