{-# LANGUAGE CPP #-} module IdeSession.Util.PortableFiles ( setFileTimes , getFileStatus , modificationTime , toExecutable , moduleNameToExeName ) where import System.PosixCompat.Types import System.PosixCompat.Files hiding (setFileTimes) #ifdef VERSION_unix import qualified System.Posix.Files as Posix #else import Foreign import Data.Time.Clock.POSIX import System.FilePath.Posix import qualified System.Win32 as Win32 import Control.Exception (bracket) #endif setFileTimes :: FilePath -> EpochTime -> EpochTime -> IO () -- Converts a module name to and executable file name moduleNameToExeName :: String -> String -- Converts a name of an a executable to the corresponding file name toExecutable :: String -> String #ifdef VERSION_unix setFileTimes = Posix.setFileTimes moduleNameToExeName = id toExecutable = id #else -- Unlike `utime`, which doesn't work for directories on Windows, this works for both for files and directories -- Mostly copied from @System.Directory@ 1.2.3.0 setFileTimes path atime mtime = bracket (openFileHandle path' Win32.gENERIC_WRITE) Win32.closeHandle $ \ handle -> with (posixToWindowsTime atime) $ \ atime' -> with (posixToWindowsTime mtime) $ \ mtime' -> Win32.failIf_ not "setFileTimes" $ Win32.c_SetFileTime handle nullPtr atime' mtime' where path' = normalise path -- handle empty paths windowsPosixEpochDifference :: Num a => a windowsPosixEpochDifference = 116444736000000000 posixToWindowsTime :: EpochTime -> Win32.FILETIME posixToWindowsTime t = Win32.FILETIME $ truncate ((realToFrac t :: POSIXTime) * 10000000 + windowsPosixEpochDifference) openFileHandle :: String -> Win32.AccessMode -> IO Win32.HANDLE openFileHandle p mode = Win32.createFile p mode share Nothing Win32.oPEN_EXISTING flags Nothing where share = Win32.fILE_SHARE_DELETE .|. Win32.fILE_SHARE_READ .|. Win32.fILE_SHARE_WRITE flags = Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_BACKUP_SEMANTICS -- required for directories moduleNameToExeName = toExecutable toExecutable e = e ++ ".exe" #endif