{-# LINE 1 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
module System.Directory.Internal.Posix where
{-# LINE 4 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
{-# LINE 5 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
{-# LINE 7 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
import Prelude ()
import System.Directory.Internal.Prelude
import System.Directory.Internal.Common
import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (POSIXTime, posixSecondsToUTCTime)
import System.FilePath (normalise)
import qualified System.Posix as Posix
foreign import ccall unsafe "free" c_free :: Ptr a -> IO ()
c_PATH_MAX :: Maybe Int
{-# LINE 21 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
c_PATH_MAX | c_PATH_MAX' > toInteger maxValue = Nothing
| otherwise = Just (fromInteger c_PATH_MAX')
where c_PATH_MAX' = (4096)
{-# LINE 24 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
maxValue = maxBound `asTypeOf` case c_PATH_MAX of ~(Just x) -> x
{-# LINE 28 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
foreign import ccall "realpath" c_realpath
:: CString -> CString -> IO CString
withRealpath :: CString -> (CString -> IO a) -> IO a
withRealpath path action = case c_PATH_MAX of
Nothing ->
bracket (realpath nullPtr) c_free action
Just pathMax ->
allocaBytes (pathMax + 1) (realpath >=> action)
where realpath = throwErrnoIfNull "" . c_realpath path
type Metadata = Posix.FileStatus
getSymbolicLinkMetadata :: FilePath -> IO Metadata
getSymbolicLinkMetadata = Posix.getSymbolicLinkStatus . normalise
getFileMetadata :: FilePath -> IO Metadata
getFileMetadata = Posix.getFileStatus . normalise
fileTypeFromMetadata :: Metadata -> FileType
fileTypeFromMetadata stat
| isLink = SymbolicLink
| isDir = Directory
| otherwise = File
where
isLink = Posix.isSymbolicLink stat
isDir = Posix.isDirectory stat
fileSizeFromMetadata :: Metadata -> Integer
fileSizeFromMetadata = fromIntegral . Posix.fileSize
accessTimeFromMetadata :: Metadata -> UTCTime
accessTimeFromMetadata =
posixSecondsToUTCTime . posix_accessTimeHiRes
modificationTimeFromMetadata :: Metadata -> UTCTime
modificationTimeFromMetadata =
posixSecondsToUTCTime . posix_modificationTimeHiRes
posix_accessTimeHiRes, posix_modificationTimeHiRes
:: Posix.FileStatus -> POSIXTime
{-# LINE 76 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
posix_accessTimeHiRes = Posix.accessTimeHiRes
posix_modificationTimeHiRes = Posix.modificationTimeHiRes
{-# LINE 82 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}
type Mode = Posix.FileMode
modeFromMetadata :: Metadata -> Mode
modeFromMetadata = Posix.fileMode
allWriteMode :: Posix.FileMode
allWriteMode =
Posix.ownerWriteMode .|.
Posix.groupWriteMode .|.
Posix.otherWriteMode
hasWriteMode :: Mode -> Bool
hasWriteMode m = m .&. allWriteMode /= 0
setWriteMode :: Bool -> Mode -> Mode
setWriteMode False m = m .&. complement allWriteMode
setWriteMode True m = m .|. allWriteMode
setFileMode :: FilePath -> Mode -> IO ()
setFileMode = Posix.setFileMode
setFilePermissions :: FilePath -> Mode -> IO ()
setFilePermissions = setFileMode
getAccessPermissions :: FilePath -> IO Permissions
getAccessPermissions path = do
m <- getFileMetadata path
let isDir = fileTypeIsDirectory (fileTypeFromMetadata m)
r <- Posix.fileAccess path True False False
w <- Posix.fileAccess path False True False
x <- Posix.fileAccess path False False True
return Permissions
{ readable = r
, writable = w
, executable = x && not isDir
, searchable = x && isDir
}
setAccessPermissions :: FilePath -> Permissions -> IO ()
setAccessPermissions path (Permissions r w e s) = do
m <- getFileMetadata path
setFileMode path (modifyBit (e || s) Posix.ownerExecuteMode .
modifyBit w Posix.ownerWriteMode .
modifyBit r Posix.ownerReadMode .
modeFromMetadata $ m)
where
modifyBit :: Bool -> Posix.FileMode -> Posix.FileMode -> Posix.FileMode
modifyBit False b m = m .&. complement b
modifyBit True b m = m .|. b
{-# LINE 134 "libraries/directory/System/Directory/Internal/Posix.hsc" #-}