1 {-# LANGUAGE CPP #-} 2 3 module Bundled.Posix( getFdStatus, getSymbolicLinkStatus, getFileStatus 4 , getFileStatusBS 5 , fileExists 6 , modificationTime, fileSize, FileStatus 7 , EpochTime, isDirectory, isRegularFile ) where 8 9 import qualified Data.ByteString.Char8 as BS 10 import Data.ByteString.Unsafe( unsafeUseAsCString ) 11 import Foreign.Marshal.Alloc ( allocaBytes ) 12 import Foreign.C.Error ( throwErrno, getErrno, eNOENT ) 13 import Foreign.C.Types ( CTime, CInt ) 14 import Foreign.Ptr ( Ptr ) 15 16 import System.Posix.Internals 17 ( CStat, c_fstat, c_stat, sizeof_stat 18 , st_mode, st_size, st_mtime, s_isdir, s_isreg ) 19 20 import System.Posix.Types ( Fd(..), CMode, EpochTime ) 21 22 #if mingw32_HOST_OS && __GLASGOW_HASKELL__ >= 612 23 import Foreign.C.String( withCWString ) 24 #else 25 import Foreign.C.String ( withCString ) 26 #endif 27 28 #if mingw32_HOST_OS 29 import Data.Int ( Int64 ) 30 31 type FileOffset = Int64 32 lstat = c_stat 33 #else 34 import System.Posix.Types ( FileOffset ) 35 import System.Posix.Internals( lstat ) 36 #endif 37 38 #if mingw32_HOST_OS && __GLASGOW_HASKELL__ >= 612 39 bsToPath s f = withCWString (BS.unpack s) f 40 strToPath = withCWString 41 #else 42 bsToPath = unsafeUseAsCString 43 strToPath = withCString 44 #endif 45 46 data FileStatus = FileStatus { 47 fst_exists :: !Bool, 48 fst_mode :: !CMode, 49 fst_mtime :: !CTime, 50 fst_size :: !FileOffset 51 } 52 53 getFdStatus :: Fd -> IO FileStatus 54 getFdStatus (Fd fd) = do 55 do_stat (c_fstat fd) 56 57 do_stat :: (Ptr CStat -> IO CInt) -> IO FileStatus 58 do_stat stat_func = do 59 allocaBytes sizeof_stat $! \p -> do 60 ret <- stat_func p 61 if (ret == -1) then do err <- getErrno 62 if (err == eNOENT) 63 then return $! (FileStatus False 0 0 0) 64 else throwErrno "do_stat" 65 else do mode <- st_mode p 66 mtime <- st_mtime p 67 size <- st_size p 68 return $! FileStatus True mode mtime size 69 {-# INLINE do_stat #-} 70 71 isDirectory :: FileStatus -> Bool 72 isDirectory = s_isdir . fst_mode 73 74 isRegularFile :: FileStatus -> Bool 75 isRegularFile = s_isreg . fst_mode 76 77 modificationTime :: FileStatus -> EpochTime 78 modificationTime = fst_mtime 79 80 fileSize :: FileStatus -> FileOffset 81 fileSize = fst_size 82 83 fileExists :: FileStatus -> Bool 84 fileExists = fst_exists 85 86 #include <sys/stat.h> 87 88 -- lstat is broken on win32 with at least GHC 6.10.3 89 getSymbolicLinkStatus :: FilePath -> IO FileStatus 90 ##if mingw32_HOST_OS 91 getSymbolicLinkStatus = getFileStatus 92 ##else 93 getSymbolicLinkStatus fp = 94 do_stat (\p -> (fp `strToPath` (`lstat` p))) 95 ##endif 96 97 getFileStatus :: FilePath -> IO FileStatus 98 getFileStatus fp = 99 do_stat (\p -> (fp `strToPath` (`lstat` p))) 100 101 -- | Requires NULL-terminated bytestring -> unsafe! Use with care. 102 getFileStatusBS :: BS.ByteString -> IO FileStatus 103 getFileStatusBS fp = 104 do_stat (\p -> (fp `bsToPath` (`lstat` p))) 105 {-# INLINE getFileStatusBS #-}