-{-# OPTIONS -fno-implicit-prelude #-}
+{-# OPTIONS -fno-implicit-prelude -#include "PrelIOUtils.h" #-}
-- ---------------------------------------------------------------------------
--- $Id: PrelPosix.hsc,v 1.11 2001/08/14 13:40:08 sewardj Exp $
--
-- POSIX support layer for the standard libraries
--
data FDType = Directory | Stream | RegularFile
deriving (Eq)
+-- NOTE: On Win32 platforms, this will only work with file descriptors
+-- referring to file handles. i.e., it'll fail for socket FDs.
fdType :: Int -> IO FDType
fdType fd =
allocaBytes (#const sizeof(struct stat)) $ \ p_stat -> do
- throwErrnoIfMinus1Retry "fileSize" $
+ throwErrnoIfMinus1Retry "fdType" $
c_fstat (fromIntegral fd) p_stat
c_mode <- (#peek struct stat, st_mode) p_stat :: IO CMode
case () of
- _ | s_isdir c_mode -> return Directory
- | s_isfifo c_mode || s_issock c_mode -> return Stream
- | s_isreg c_mode -> return RegularFile
- | otherwise -> ioException ioe_unknownfiletype
+ _ | s_isdir c_mode -> return Directory
+ | s_isfifo c_mode -> return Stream
+ | s_issock c_mode -> return Stream
+ | s_ischr c_mode -> return Stream
+ | s_isreg c_mode -> return RegularFile
+ | s_isblk c_mode -> return RegularFile
+ | otherwise -> ioException ioe_unknownfiletype
+ -- we consider character devices to be streams (eg. ttys),
+ -- whereas block devices are more like regular files because they
+ -- are seekable.
ioe_unknownfiletype = IOError Nothing UnsupportedOperation "fdType"
"unknown file type" Nothing
-foreign import "s_isreg_wrap" unsafe s_isreg :: CMode -> Bool
-#def inline int s_isreg_wrap(m) { return S_ISREG(m); }
-
-foreign import "s_isdir_wrap" unsafe s_isdir :: CMode -> Bool
-#def inline int s_isdir_wrap(m) { return S_ISDIR(m); }
-
-foreign import "s_isfifo_wrap" unsafe s_isfifo :: CMode -> Bool
-#def inline int s_isfifo_wrap(m) { return S_ISFIFO(m); }
+foreign import "s_isreg_PrelPosix_wrap" unsafe s_isreg :: CMode -> Bool
+foreign import "s_isdir_PrelPosix_wrap" unsafe s_isdir :: CMode -> Bool
+foreign import "s_isfifo_PrelPosix_wrap" unsafe s_isfifo :: CMode -> Bool
+foreign import "s_ischr_PrelPosix_wrap" unsafe s_ischr :: CMode -> Bool
+foreign import "s_isblk_PrelPosix_wrap" unsafe s_isblk :: CMode -> Bool
#ifndef mingw32_TARGET_OS
-foreign import "s_issock_wrap" unsafe s_issock :: CMode -> Bool
-#def inline int s_issock_wrap(m) { return S_ISSOCK(m); }
+foreign import "s_issock_PrelPosix_wrap" unsafe s_issock :: CMode -> Bool
#else
s_issock :: CMode -> Bool
s_issock cmode = False
setNonBlockingFD fd = do
flags <- throwErrnoIfMinus1Retry "setNonBlockingFD"
(fcntl_read (fromIntegral fd) (#const F_GETFL))
- throwErrnoIfMinus1Retry "setNonBlockingFD"
- (fcntl_write (fromIntegral fd)
- (#const F_SETFL) (flags .|. #const O_NONBLOCK))
+ -- 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.
+ fcntl_write (fromIntegral fd)
+ (#const F_SETFL) (flags .|. #const O_NONBLOCK)
#else
-- bogus defns for win32
foreign import "close" unsafe
c_close :: CInt -> IO CInt
+#ifdef mingw32_TARGET_OS
+closeFd :: Bool -> CInt -> IO CInt
+closeFd isStream fd
+ | isStream = c_closesocket fd
+ | otherwise = c_close fd
+
+foreign import "closesocket" unsafe
+ c_closesocket :: CInt -> IO CInt
+#endif
+
foreign import "lseek" unsafe
c_lseek :: CInt -> COff -> CInt -> IO COff
foreign import "fork" unsafe
fork :: IO CPid
-foreign import "sigemptyset" unsafe
+foreign import "sigemptyset_PrelPosix_wrap" unsafe
c_sigemptyset :: Ptr CSigset -> IO ()
foreign import "sigaddset" unsafe