{-# LANGUAGE CPP #-} module Bundled.Posix( getFdStatus, getSymbolicLinkStatus, getFileStatus , getFileStatusBS , fileExists , modificationTime, fileSize, FileStatus , EpochTime, isDirectory ) where import qualified Data.ByteString.Char8 as BS import Data.ByteString.Unsafe( unsafeUseAsCString ) import Foreign.Marshal.Alloc ( allocaBytes ) import Foreign.C.Error ( throwErrno, getErrno, eNOENT ) import Foreign.C.String ( withCString ) import Foreign.C.Types ( CTime, CInt ) import Foreign.Ptr ( Ptr ) import System.Posix.Internals ( CStat, c_fstat, lstat, c_stat, sizeof_stat , st_mode, st_size, st_mtime, s_isdir ) import System.Posix.Types ( Fd(..), CMode, EpochTime ) #if mingw32_HOST_OS import Data.Int ( Int64 ) #else import System.Posix.Types ( FileOffset ) #endif ##if mingw32_HOST_OS type FileOffset = Int64 ##endif data FileStatus = FileStatus { fst_exists :: Bool, fst_mode :: CMode, fst_mtime :: CTime, fst_size :: FileOffset } getFdStatus :: Fd -> IO FileStatus getFdStatus (Fd fd) = do do_stat (c_fstat fd) do_stat :: (Ptr CStat -> IO CInt) -> IO FileStatus do_stat stat_func = do allocaBytes sizeof_stat $ \p -> do ret <- stat_func p err <- getErrno case (ret == -1 && err == eNOENT, ret == 0) of (True, _) -> return (FileStatus False 0 0 0) (False, True) -> do mode <- st_mode p mtime <- st_mtime p size <- st_size p return (FileStatus True mode mtime (fromIntegral size)) _ -> throwErrno "do_stat" {-# INLINE do_stat #-} isDirectory :: FileStatus -> Bool isDirectory = s_isdir . fst_mode modificationTime :: FileStatus -> EpochTime modificationTime = fst_mtime fileSize :: FileStatus -> FileOffset fileSize = fst_size fileExists :: FileStatus -> Bool fileExists = fst_exists #include -- lstat is broken on win32 with at least GHC 6.10.3 getSymbolicLinkStatus :: FilePath -> IO FileStatus ##if mingw32_HOST_OS getSymbolicLinkStatus = getFileStatus ##else getSymbolicLinkStatus fp = do_stat (\p -> (fp `withCString` (`lstat` p))) ##endif getFileStatus :: FilePath -> IO FileStatus getFileStatus fp = do_stat (\p -> (fp `withCString` (`c_stat` p))) -- | Requires NULL-terminated bytestring -> unsafe! Use with care. getFileStatusBS :: BS.ByteString -> IO FileStatus getFileStatusBS fp = do_stat (\p -> (fp `unsafeUseAsCString` (`lstat` p))) {-# INLINE getFileStatusBS #-}