module System.File
( IO.Handle
, IO.IOMode(..)
, copyFile
, getModified
, getSize
, openFile
, withFile
, readFile
, writeFile
, appendFile
, openTextFile
, withTextFile
, readTextFile
, writeTextFile
, appendTextFile
) where
import Prelude hiding (FilePath, readFile, writeFile, appendFile)
import qualified Data.ByteString as B
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified System.IO as IO
import System.FilePath (FilePath)
import System.FileIO.Internal (encode)
#ifdef CABAL_OS_WINDOWS
import qualified Control.Exception as Exc
import Data.Bits ((.|.))
import Data.Time ( UTCTime(..)
, fromGregorian
, secondsToDiffTime
, picosecondsToDiffTime)
import qualified System.Win32 as Win32
#else
import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import qualified System.Posix as Posix
#endif
import qualified "directory" System.Directory as SD
copyFile :: FilePath
-> FilePath
-> IO ()
copyFile old new = SD.copyFile (encode old) (encode new)
getModified :: FilePath -> IO UTCTime
getModified path = do
#ifdef CABAL_OS_WINDOWS
info <- withHANDLE path Win32.getFileInformationByHandle
let ftime = Win32.bhfiLastWriteTime info
stime <- Win32.fileTimeToSystemTime ftime
let date = fromGregorian
(fromIntegral (Win32.wYear stime))
(fromIntegral (Win32.wMonth stime))
(fromIntegral (Win32.wDay stime))
let seconds = secondsToDiffTime $
(toInteger (Win32.wHour stime) * 3600) +
(toInteger (Win32.wMinute stime) * 60) +
(toInteger (Win32.wSecond stime))
let msecs = picosecondsToDiffTime $
(toInteger (Win32.wMilliseconds stime) * 1000000000)
return (UTCTime date (seconds + msecs))
#else
stat <- Posix.getFileStatus (encode path)
let mtime = Posix.modificationTime stat
return (posixSecondsToUTCTime (realToFrac mtime))
#endif
getSize :: FilePath -> IO Integer
getSize path = do
#ifdef CABAL_OS_WINDOWS
info <- withHANDLE path Win32.getFileInformationByHandle
return (toInteger (Win32.bhfiSize info))
#else
stat <- Posix.getFileStatus (encode path)
return (toInteger (Posix.fileSize stat))
#endif
openFile :: FilePath -> IO.IOMode -> IO IO.Handle
openFile path = IO.openBinaryFile (encode path)
withFile :: FilePath -> IO.IOMode -> (IO.Handle -> IO a) -> IO a
withFile path = IO.withBinaryFile (encode path)
readFile :: FilePath -> IO B.ByteString
readFile path = B.readFile (encode path)
writeFile :: FilePath -> B.ByteString -> IO ()
writeFile path = B.writeFile (encode path)
appendFile :: FilePath -> B.ByteString -> IO ()
appendFile path = B.appendFile (encode path)
openTextFile :: FilePath -> IO.IOMode -> IO IO.Handle
openTextFile path = IO.openFile (encode path)
withTextFile :: FilePath -> IO.IOMode -> (IO.Handle -> IO a) -> IO a
withTextFile path = IO.withFile (encode path)
readTextFile :: FilePath -> IO T.Text
readTextFile path = T.readFile (encode path)
writeTextFile :: FilePath -> T.Text -> IO ()
writeTextFile path = T.writeFile (encode path)
appendTextFile :: FilePath -> T.Text -> IO ()
appendTextFile path = T.appendFile (encode path)
#ifdef CABAL_OS_WINDOWS
withHANDLE :: FilePath -> (Win32.HANDLE -> IO a) -> IO a
withHANDLE path = Exc.bracket open close where
open = Win32.createFile
(encode path)
Win32.gENERIC_READ
(Win32.fILE_SHARE_READ .|. Win32.fILE_SHARE_WRITE)
Nothing
Win32.oPEN_EXISTING
0
Nothing
close = Win32.closeHandle
#endif