1 {-# OPTIONS_GHC -XNoImplicitPrelude -XBangPatterns -fno-warn-identities #-}
2 -- Whether there are identities depends on the platform
3 {-# OPTIONS_HADDOCK hide #-}
4 -----------------------------------------------------------------------------
7 -- Copyright : (c) The University of Glasgow, 1994-2008
8 -- License : see libraries/base/LICENSE
10 -- Maintainer : libraries@haskell.org
11 -- Stability : internal
12 -- Portability : non-portable
14 -- Raw read/write operations on file descriptors
16 -----------------------------------------------------------------------------
20 openFile, mkFD, release,
22 readRawBufferPtr, readRawBufferPtrNoBlock, writeRawBufferPtr,
38 import GHC.IO.BufferedIO
39 import qualified GHC.IO.Device
40 import GHC.IO.Device (SeekMode(..), IODeviceType(..))
42 import GHC.IO.Exception
46 import qualified System.Posix.Internals
47 import System.Posix.Internals hiding (FD, setEcho, getEcho)
48 import System.Posix.Types
54 -- -----------------------------------------------------------------------------
55 -- The file-descriptor IO device
58 fdFD :: {-# UNPACK #-} !CInt,
59 #ifdef mingw32_HOST_OS
60 -- On Windows, a socket file descriptor needs to be read and written
61 -- using different functions (send/recv).
62 fdIsSocket_ :: {-# UNPACK #-} !Int
64 -- On Unix we need to know whether this FD has O_NONBLOCK set.
65 -- If it has, then we can use more efficient routines to read/write to it.
66 -- It is always safe for this to be off.
67 fdIsNonBlocking :: {-# UNPACK #-} !Int
72 #ifdef mingw32_HOST_OS
73 fdIsSocket :: FD -> Bool
74 fdIsSocket fd = fdIsSocket_ fd /= 0
77 instance Show FD where
78 show fd = show (fdFD fd)
80 instance GHC.IO.Device.RawIO FD where
82 readNonBlocking = fdReadNonBlocking
84 writeNonBlocking = fdWriteNonBlocking
86 instance GHC.IO.Device.IODevice FD where
89 isTerminal = isTerminal
90 isSeekable = isSeekable
102 -- We used to use System.Posix.Internals.dEFAULT_BUFFER_SIZE, which is
103 -- taken from the value of BUFSIZ on the current platform. This value
104 -- varies too much though: it is 512 on Windows, 1024 on OS X and 8192
105 -- on Linux. So let's just use a decent size on every platform:
106 dEFAULT_FD_BUFFER_SIZE :: Int
107 dEFAULT_FD_BUFFER_SIZE = 8096
109 instance BufferedIO FD where
110 newBuffer _dev state = newByteBuffer dEFAULT_FD_BUFFER_SIZE state
111 fillReadBuffer fd buf = readBuf' fd buf
112 fillReadBuffer0 fd buf = readBufNonBlocking fd buf
113 flushWriteBuffer fd buf = writeBuf' fd buf
114 flushWriteBuffer0 fd buf = writeBufNonBlocking fd buf
116 readBuf' :: FD -> Buffer Word8 -> IO (Int, Buffer Word8)
119 puts ("readBuf fd=" ++ show fd ++ " " ++ summaryBuffer buf ++ "\n")
120 (r,buf') <- readBuf fd buf
122 puts ("after: " ++ summaryBuffer buf' ++ "\n")
125 writeBuf' :: FD -> Buffer Word8 -> IO (Buffer Word8)
126 writeBuf' fd buf = do
128 puts ("writeBuf fd=" ++ show fd ++ " " ++ summaryBuffer buf ++ "\n")
131 -- -----------------------------------------------------------------------------
134 -- | Open a file and make an 'FD' for it. Truncates the file to zero
135 -- size when the `IOMode` is `WriteMode`. Puts the file descriptor
136 -- into non-blocking mode on Unix systems.
137 openFile :: FilePath -> IOMode -> IO (FD,IODeviceType)
138 openFile filepath iomode =
139 withFilePath filepath $ \ f ->
142 oflags1 = case iomode of
143 ReadMode -> read_flags
144 #ifdef mingw32_HOST_OS
145 WriteMode -> write_flags .|. o_TRUNC
147 WriteMode -> write_flags
149 ReadWriteMode -> rw_flags
150 AppendMode -> append_flags
152 #ifdef mingw32_HOST_OS
153 binary_flags = o_BINARY
158 oflags = oflags1 .|. binary_flags
161 -- the old implementation had a complicated series of three opens,
162 -- which is perhaps because we have to be careful not to open
163 -- directories. However, the man pages I've read say that open()
164 -- always returns EISDIR if the file is a directory and was opened
165 -- for writing, so I think we're ok with a single open() here...
166 fd <- throwErrnoIfMinus1Retry "openFile"
167 (c_open f oflags 0o666)
169 (fD,fd_type) <- mkFD fd iomode Nothing{-no stat-}
170 False{-not a socket-}
171 True{-is non-blocking-}
172 `catchAny` \e -> do _ <- c_close fd
175 #ifndef mingw32_HOST_OS
176 -- we want to truncate() if this is an open in WriteMode, but only
177 -- if the target is a RegularFile. ftruncate() fails on special files
179 if iomode == WriteMode && fd_type == RegularFile
186 std_flags, output_flags, read_flags, write_flags, rw_flags,
188 std_flags = o_NONBLOCK .|. o_NOCTTY
189 output_flags = std_flags .|. o_CREAT
190 read_flags = std_flags .|. o_RDONLY
191 write_flags = output_flags .|. o_WRONLY
192 rw_flags = output_flags .|. o_RDWR
193 append_flags = write_flags .|. o_APPEND
196 -- | Make a 'FD' from an existing file descriptor. Fails if the FD
197 -- refers to a directory. If the FD refers to a file, `mkFD` locks
198 -- the file according to the Haskell 98 single writer/multiple reader
199 -- locking semantics (this is why we need the `IOMode` argument too).
202 -> Maybe (IODeviceType, CDev, CIno)
203 -- the results of fdStat if we already know them, or we want
204 -- to prevent fdToHandle_stat from doing its own stat.
205 -- These are used for:
206 -- - we fail if the FD refers to a directory
207 -- - if the FD refers to a file, we lock it using (cdev,cino)
208 -> Bool -- ^ is a socket (on Windows)
209 -> Bool -- ^ is in non-blocking mode on Unix
210 -> IO (FD,IODeviceType)
212 mkFD fd iomode mb_stat is_socket is_nonblock = do
214 let _ = (is_socket, is_nonblock) -- warning suppression
219 Just stat -> return stat
221 let write = case iomode of
225 #ifdef mingw32_HOST_OS
226 _ <- setmode fd True -- unconditionally set binary mode
227 let _ = (dev,ino,write) -- warning suppression
232 ioException (IOError Nothing InappropriateType "openFile"
233 "is a directory" Nothing Nothing)
235 #ifndef mingw32_HOST_OS
236 -- regular files need to be locked
238 -- On Windows we use explicit exclusion via sopen() to implement
239 -- this locking (see __hscore_open()); on Unix we have to
240 -- implment it in the RTS.
241 r <- lockFile fd dev ino (fromBool write)
243 ioException (IOError Nothing ResourceBusy "openFile"
244 "file is locked" Nothing Nothing)
247 _other_type -> return ()
249 return (FD{ fdFD = fd,
250 #ifndef mingw32_HOST_OS
251 fdIsNonBlocking = fromEnum is_nonblock
253 fdIsSocket_ = fromEnum is_socket
258 #ifdef mingw32_HOST_OS
259 foreign import ccall unsafe "__hscore_setmode"
260 setmode :: CInt -> Bool -> IO CInt
263 -- -----------------------------------------------------------------------------
264 -- Standard file descriptors
267 stdFD fd = FD { fdFD = fd,
268 #ifdef mingw32_HOST_OS
272 -- We don't set non-blocking mode on standard handles, because it may
273 -- confuse other applications attached to the same TTY/pipe
274 -- see Note [nonblock]
278 stdin, stdout, stderr :: FD
283 -- -----------------------------------------------------------------------------
284 -- Operations on file descriptors
288 #ifndef mingw32_HOST_OS
289 (flip finally) (release fd) $
291 do let closer realFd =
292 throwErrnoIfMinus1Retry_ "GHC.IO.FD.close" $
293 #ifdef mingw32_HOST_OS
294 if fdIsSocket fd then
295 c_closesocket (fromIntegral realFd)
298 c_close (fromIntegral realFd)
299 closeFdWith closer (fromIntegral (fdFD fd))
301 release :: FD -> IO ()
302 #ifdef mingw32_HOST_OS
303 release _ = return ()
305 release fd = do _ <- unlockFile (fdFD fd)
309 #ifdef mingw32_HOST_OS
310 foreign import stdcall unsafe "HsBase.h closesocket"
311 c_closesocket :: CInt -> IO CInt
314 isSeekable :: FD -> IO Bool
317 return (t == RegularFile || t == RawDevice)
319 seek :: FD -> SeekMode -> Integer -> IO ()
320 seek fd mode off = do
321 throwErrnoIfMinus1Retry_ "seek" $
322 c_lseek (fdFD fd) (fromIntegral off) seektype
325 seektype = case mode of
326 AbsoluteSeek -> sEEK_SET
327 RelativeSeek -> sEEK_CUR
328 SeekFromEnd -> sEEK_END
330 tell :: FD -> IO Integer
333 (throwErrnoIfMinus1Retry "hGetPosn" $
334 c_lseek (fdFD fd) 0 sEEK_CUR)
336 getSize :: FD -> IO Integer
337 getSize fd = fdFileSize (fdFD fd)
339 setSize :: FD -> Integer -> IO ()
341 throwErrnoIf_ (/=0) "GHC.IO.FD.setSize" $
342 c_ftruncate (fdFD fd) (fromIntegral size)
344 devType :: FD -> IO IODeviceType
345 devType fd = do (ty,_,_) <- fdStat (fdFD fd); return ty
349 newfd <- throwErrnoIfMinus1 "GHC.IO.FD.dup" $ c_dup (fdFD fd)
350 return fd{ fdFD = newfd }
352 dup2 :: FD -> FD -> IO FD
354 -- Windows' dup2 does not return the new descriptor, unlike Unix
355 throwErrnoIfMinus1_ "GHC.IO.FD.dup2" $
356 c_dup2 (fdFD fd) (fdFD fdto)
357 return fd{ fdFD = fdFD fdto } -- original FD, with the new fdFD
359 setNonBlockingMode :: FD -> Bool -> IO FD
360 setNonBlockingMode fd set = do
361 setNonBlockingFD (fdFD fd) set
362 #if defined(mingw32_HOST_OS)
365 return fd{ fdIsNonBlocking = fromEnum set }
368 ready :: FD -> Bool -> Int -> IO Bool
369 ready fd write msecs = do
370 r <- throwErrnoIfMinus1Retry "GHC.IO.FD.ready" $
371 fdReady (fdFD fd) (fromIntegral $ fromEnum $ write)
373 #if defined(mingw32_HOST_OS)
374 (fromIntegral $ fromEnum $ fdIsSocket fd)
378 return (toEnum (fromIntegral r))
380 foreign import ccall safe "fdReady"
381 fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt
383 -- ---------------------------------------------------------------------------
384 -- Terminal-related stuff
386 isTerminal :: FD -> IO Bool
388 #if defined(mingw32_HOST_OS)
389 is_console (fdFD fd) >>= return.toBool
391 c_isatty (fdFD fd) >>= return.toBool
394 setEcho :: FD -> Bool -> IO ()
395 setEcho fd on = System.Posix.Internals.setEcho (fdFD fd) on
397 getEcho :: FD -> IO Bool
398 getEcho fd = System.Posix.Internals.getEcho (fdFD fd)
400 setRaw :: FD -> Bool -> IO ()
401 setRaw fd raw = System.Posix.Internals.setCooked (fdFD fd) (not raw)
403 -- -----------------------------------------------------------------------------
404 -- Reading and Writing
406 fdRead :: FD -> Ptr Word8 -> Int -> IO Int
408 = do { r <- readRawBufferPtr "GHC.IO.FD.fdRead" fd ptr 0 (fromIntegral bytes)
409 ; return (fromIntegral r) }
411 fdReadNonBlocking :: FD -> Ptr Word8 -> Int -> IO (Maybe Int)
412 fdReadNonBlocking fd ptr bytes = do
413 r <- readRawBufferPtrNoBlock "GHC.IO.FD.fdReadNonBlocking" fd ptr
414 0 (fromIntegral bytes)
415 case fromIntegral r of
416 (-1) -> return (Nothing)
420 fdWrite :: FD -> Ptr Word8 -> Int -> IO ()
421 fdWrite fd ptr bytes = do
422 res <- writeRawBufferPtr "GHC.IO.FD.fdWrite" fd ptr 0 (fromIntegral bytes)
423 let res' = fromIntegral res
425 then fdWrite fd (ptr `plusPtr` res') (bytes - res')
428 -- XXX ToDo: this isn't non-blocking
429 fdWriteNonBlocking :: FD -> Ptr Word8 -> Int -> IO Int
430 fdWriteNonBlocking fd ptr bytes = do
431 res <- writeRawBufferPtrNoBlock "GHC.IO.FD.fdWriteNonBlocking" fd ptr 0
433 return (fromIntegral res)
435 -- -----------------------------------------------------------------------------
438 -- Low level routines for reading/writing to (raw)buffers:
440 #ifndef mingw32_HOST_OS
445 Unix has broken semantics when it comes to non-blocking I/O: you can
446 set the O_NONBLOCK flag on an FD, but it applies to the all other FDs
447 attached to the same underlying file, pipe or TTY; there's no way to
448 have private non-blocking behaviour for an FD. See bug #724.
450 We fix this by only setting O_NONBLOCK on FDs that we create; FDs that
451 come from external sources or are exposed externally are left in
452 blocking mode. This solution has some problems though. We can't
453 completely simulate a non-blocking read without O_NONBLOCK: several
454 cases are wrong here. The cases that are wrong:
456 * reading/writing to a blocking FD in non-threaded mode.
457 In threaded mode, we just make a safe call to read().
458 In non-threaded mode we call select() before attempting to read,
459 but that leaves a small race window where the data can be read
460 from the file descriptor before we issue our blocking read().
461 * readRawBufferNoBlock for a blocking FD
465 In the threaded RTS we could just make safe calls to read()/write()
466 for file descriptors in blocking mode without worrying about blocking
467 other threads, but the problem with this is that the thread will be
468 uninterruptible while it is blocked in the foreign call. See #2363.
469 So now we always call fdReady() before reading, and if fdReady
470 indicates that there's no data, we call threadWaitRead.
474 readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO Int
475 readRawBufferPtr loc !fd buf off len
476 | isNonBlocking fd = unsafe_read -- unsafe is ok, it can't block
477 | otherwise = do r <- throwErrnoIfMinus1 loc
478 (unsafe_fdReady (fdFD fd) 0 0 0)
481 else do threadWaitRead (fromIntegral (fdFD fd)); read
483 do_read call = fromIntegral `fmap`
484 throwErrnoIfMinus1RetryMayBlock loc call
485 (threadWaitRead (fromIntegral (fdFD fd)))
486 read = if threaded then safe_read else unsafe_read
487 unsafe_read = do_read (c_read (fdFD fd) (buf `plusPtr` off) len)
488 safe_read = do_read (c_safe_read (fdFD fd) (buf `plusPtr` off) len)
490 -- return: -1 indicates EOF, >=0 is bytes read
491 readRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO Int
492 readRawBufferPtrNoBlock loc !fd buf off len
493 | isNonBlocking fd = unsafe_read -- unsafe is ok, it can't block
494 | otherwise = do r <- unsafe_fdReady (fdFD fd) 0 0 0
495 if r /= 0 then safe_read
497 -- XXX see note [nonblock]
499 do_read call = do r <- throwErrnoIfMinus1RetryOnBlock loc call (return (-1))
503 n -> return (fromIntegral n)
504 unsafe_read = do_read (c_read (fdFD fd) (buf `plusPtr` off) len)
505 safe_read = do_read (c_safe_read (fdFD fd) (buf `plusPtr` off) len)
507 writeRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
508 writeRawBufferPtr loc !fd buf off len
509 | isNonBlocking fd = unsafe_write -- unsafe is ok, it can't block
510 | otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0
513 else do threadWaitWrite (fromIntegral (fdFD fd)); write
515 do_write call = fromIntegral `fmap`
516 throwErrnoIfMinus1RetryMayBlock loc call
517 (threadWaitWrite (fromIntegral (fdFD fd)))
518 write = if threaded then safe_write else unsafe_write
519 unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len)
520 safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)
522 writeRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
523 writeRawBufferPtrNoBlock loc !fd buf off len
524 | isNonBlocking fd = unsafe_write -- unsafe is ok, it can't block
525 | otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0
529 do_write call = do r <- throwErrnoIfMinus1RetryOnBlock loc call (return (-1))
532 n -> return (fromIntegral n)
533 write = if threaded then safe_write else unsafe_write
534 unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len)
535 safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)
537 isNonBlocking :: FD -> Bool
538 isNonBlocking fd = fdIsNonBlocking fd /= 0
540 foreign import ccall unsafe "fdReady"
541 unsafe_fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt
543 #else /* mingw32_HOST_OS.... */
545 readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
546 readRawBufferPtr loc !fd buf off len
547 | threaded = blockingReadRawBufferPtr loc fd buf off len
548 | otherwise = asyncReadRawBufferPtr loc fd buf off len
550 writeRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
551 writeRawBufferPtr loc !fd buf off len
552 | threaded = blockingWriteRawBufferPtr loc fd buf off len
553 | otherwise = asyncWriteRawBufferPtr loc fd buf off len
555 readRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
556 readRawBufferPtrNoBlock = readRawBufferPtr
558 writeRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
559 writeRawBufferPtrNoBlock = writeRawBufferPtr
561 -- Async versions of the read/write primitives, for the non-threaded RTS
563 asyncReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
564 asyncReadRawBufferPtr loc !fd buf off len = do
565 (l, rc) <- asyncRead (fromIntegral (fdFD fd)) (fdIsSocket_ fd)
566 (fromIntegral len) (buf `plusPtr` off)
569 ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)
570 else return (fromIntegral l)
572 asyncWriteRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
573 asyncWriteRawBufferPtr loc !fd buf off len = do
574 (l, rc) <- asyncWrite (fromIntegral (fdFD fd)) (fdIsSocket_ fd)
575 (fromIntegral len) (buf `plusPtr` off)
578 ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)
579 else return (fromIntegral l)
581 -- Blocking versions of the read/write primitives, for the threaded RTS
583 blockingReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
584 blockingReadRawBufferPtr loc fd buf off len
585 = fmap fromIntegral $ throwErrnoIfMinus1Retry loc $
587 then c_safe_recv (fdFD fd) (buf `plusPtr` off) len 0
588 else c_safe_read (fdFD fd) (buf `plusPtr` off) len
590 blockingWriteRawBufferPtr :: String -> FD -> Ptr Word8-> Int -> CSize -> IO CInt
591 blockingWriteRawBufferPtr loc fd buf off len
592 = fmap fromIntegral $ throwErrnoIfMinus1Retry loc $
594 then c_safe_send (fdFD fd) (buf `plusPtr` off) len 0
596 r <- c_safe_write (fdFD fd) (buf `plusPtr` off) len
597 when (r == -1) c_maperrno
599 -- we don't trust write() to give us the correct errno, and
600 -- instead do the errno conversion from GetLastError()
601 -- ourselves. The main reason is that we treat ERROR_NO_DATA
602 -- (pipe is closing) as EPIPE, whereas write() returns EINVAL
603 -- for this case. We need to detect EPIPE correctly, because it
604 -- shouldn't be reported as an error when it happens on stdout.
606 foreign import ccall unsafe "maperrno" -- in Win32Utils.c
609 -- NOTE: "safe" versions of the read/write calls for use by the threaded RTS.
610 -- These calls may block, but that's ok.
612 foreign import stdcall safe "recv"
613 c_safe_recv :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize
615 foreign import stdcall safe "send"
616 c_safe_send :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize
620 foreign import ccall "rtsSupportsBoundThreads" threaded :: Bool
622 -- -----------------------------------------------------------------------------
625 #ifndef mingw32_HOST_OS
626 throwErrnoIfMinus1RetryOnBlock :: String -> IO CSsize -> IO CSsize -> IO CSsize
627 throwErrnoIfMinus1RetryOnBlock loc f on_block =
630 if (res :: CSsize) == -1
634 then throwErrnoIfMinus1RetryOnBlock loc f on_block
635 else if err == eWOULDBLOCK || err == eAGAIN
641 -- -----------------------------------------------------------------------------
644 #ifndef mingw32_HOST_OS
645 foreign import ccall unsafe "lockFile"
646 lockFile :: CInt -> CDev -> CIno -> CInt -> IO CInt
648 foreign import ccall unsafe "unlockFile"
649 unlockFile :: CInt -> IO CInt
652 puts :: String -> IO ()
653 puts s = do _ <- withCStringLen s $ \(p,len) ->
654 c_write 1 (castPtr p) (fromIntegral len)