module System.Posix.Files where import Foreign.Marshal.Alloc ( allocaBytes ) import Foreign.C.Error ( throwErrnoIfMinus1Retry ) import Foreign.C.String ( withCString ) import Foreign.C.Types ( CTime, CInt ) import Foreign.Ptr ( Ptr ) import System.Posix.Internals ( FDType, CStat, c_fstat, lstat, sizeof_stat, statGetType, st_mode, st_size, st_mtime, s_isreg, s_isdir, s_isfifo, ) import System.Posix.Types ( Fd(..), CMode, COff, EpochTime, FileOffset, FileMode ) import Data.Bits ( (.|.) ) data FileStatus = FileStatus { fst_type :: FDType, fst_mode :: CMode, fst_mtime :: CTime, fst_size :: COff } 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 throwErrnoIfMinus1Retry "do_stat" $ stat_func p tp <- statGetType p mode <- st_mode p mtime <- st_mtime p size <- st_size p return (FileStatus tp mode mtime size) isNamedPipe :: FileStatus -> Bool isNamedPipe = s_isfifo . fst_mode isDirectory :: FileStatus -> Bool isDirectory = s_isdir . fst_mode isRegularFile :: FileStatus -> Bool isRegularFile = s_isreg . fst_mode isSymbolicLink :: FileStatus -> Bool isSymbolicLink = const False linkCount :: FileStatus -> Int linkCount _ = 1 modificationTime :: FileStatus -> EpochTime modificationTime = fst_mtime fileSize :: FileStatus -> FileOffset fileSize = fst_size #include stdFileMode :: FileMode stdFileMode = (#const S_IRUSR) .|. (#const S_IWUSR) getSymbolicLinkStatus :: FilePath -> IO FileStatus getSymbolicLinkStatus fp = do_stat (\p -> (fp `withCString` (`lstat` p)))