X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FIO%2FFD.hs;h=3ba155ed22055f348c99ffdf46a7cdc9c70c27cb;hb=b22112520b01c4906eebd0b6894d4bf2665c11e2;hp=4425a3a76d2a3fe9b47d42d674267ab7da640c09;hpb=18d76310cb679667c9d3e491277c283a0dccee06;p=ghc-base.git diff --git a/GHC/IO/FD.hs b/GHC/IO/FD.hs index 4425a3a..3ba155e 100644 --- a/GHC/IO/FD.hs +++ b/GHC/IO/FD.hs @@ -1,4 +1,5 @@ -{-# OPTIONS_GHC -XNoImplicitPrelude -XBangPatterns #-} +{-# OPTIONS_GHC -XNoImplicitPrelude -XBangPatterns -fno-warn-identities #-} +-- Whether there are identities depends on the platform {-# OPTIONS_HADDOCK hide #-} ----------------------------------------------------------------------------- -- | @@ -37,7 +38,7 @@ import GHC.IO.Buffer import GHC.IO.BufferedIO import qualified GHC.IO.Device import GHC.IO.Device (SeekMode(..), IODeviceType(..)) -import GHC.Conc +import GHC.Conc.IO import GHC.IO.Exception import Foreign @@ -156,7 +157,7 @@ openFile filepath iomode = -- always returns EISDIR if the file is a directory and was opened -- for writing, so I think we're ok with a single open() here... fd <- throwErrnoIfMinus1Retry "openFile" - (c_open f (fromIntegral oflags) 0o666) + (c_open f oflags 0o666) (fD,fd_type) <- mkFD fd iomode Nothing{-no stat-} False{-not a socket-} @@ -280,13 +281,15 @@ close fd = #ifndef mingw32_HOST_OS (flip finally) (release fd) $ do #endif - throwErrnoIfMinus1Retry_ "GHC.IO.FD.close" $ + let closer realFd = + throwErrnoIfMinus1Retry_ "GHC.IO.FD.close" $ #ifdef mingw32_HOST_OS - if fdIsSocket fd then - c_closesocket (fdFD fd) - else + if fdIsSocket fd then + c_closesocket (fromIntegral realFd) + else #endif - c_close (fdFD fd) + c_close (fromIntegral realFd) + closeFdWith closer (fromIntegral (fdFD fd)) release :: FD -> IO () #ifdef mingw32_HOST_OS @@ -374,7 +377,12 @@ foreign import ccall safe "fdReady" -- Terminal-related stuff isTerminal :: FD -> IO Bool -isTerminal fd = c_isatty (fdFD fd) >>= return.toBool +isTerminal fd = +#if defined(mingw32_HOST_OS) + is_console (fdFD fd) >>= return.toBool +#else + c_isatty (fdFD fd) >>= return.toBool +#endif setEcho :: FD -> Bool -> IO () setEcho fd on = System.Posix.Internals.setEcho (fdFD fd) on @@ -389,17 +397,17 @@ setRaw fd raw = System.Posix.Internals.setCooked (fdFD fd) (not raw) -- Reading and Writing fdRead :: FD -> Ptr Word8 -> Int -> IO Int -fdRead fd ptr bytes = do - r <- readRawBufferPtr "GHC.IO.FD.fdRead" fd ptr 0 (fromIntegral bytes) - return (fromIntegral r) +fdRead fd ptr bytes + = do { r <- readRawBufferPtr "GHC.IO.FD.fdRead" fd ptr 0 (fromIntegral bytes) + ; return (fromIntegral r) } fdReadNonBlocking :: FD -> Ptr Word8 -> Int -> IO (Maybe Int) fdReadNonBlocking fd ptr bytes = do r <- readRawBufferPtrNoBlock "GHC.IO.FD.fdReadNonBlocking" fd ptr 0 (fromIntegral bytes) - case r of + case fromIntegral r of (-1) -> return (Nothing) - n -> return (Just (fromIntegral n)) + n -> return (Just n) fdWrite :: FD -> Ptr Word8 -> Int -> IO () @@ -577,7 +585,19 @@ blockingWriteRawBufferPtr loc fd buf off len = fmap fromIntegral $ throwErrnoIfMinus1Retry loc $ if fdIsSocket fd then c_safe_send (fdFD fd) (buf `plusPtr` off) len 0 - else c_safe_write (fdFD fd) (buf `plusPtr` off) len + else do + r <- c_safe_write (fdFD fd) (buf `plusPtr` off) len + when (r == -1) c_maperrno + return r + -- we don't trust write() to give us the correct errno, and + -- instead do the errno conversion from GetLastError() + -- ourselves. The main reason is that we treat ERROR_NO_DATA + -- (pipe is closing) as EPIPE, whereas write() returns EINVAL + -- for this case. We need to detect EPIPE correctly, because it + -- shouldn't be reported as an error when it happens on stdout. + +foreign import ccall unsafe "maperrno" -- in Win32Utils.c + c_maperrno :: IO () -- NOTE: "safe" versions of the read/write calls for use by the threaded RTS. -- These calls may block, but that's ok.