module Posixutil.CopyFile(
copyFile,
copyFileWE,
copyStringToFile,
copyStringToFileCheck,
copyFileToString,
copyFileToStringCheck,
copyICStringLenToFile,
copyFileToICStringLenCheck,
copyCStringLenToFile,
copyFileToCStringLen,
copyFileToICStringLen,
) where
import System.IO as IO
import System.IO.Error as IO
import qualified System.IO.Error as IOErr
import Foreign.C
import Control.Exception
import qualified System.Directory as Dir
import Util.Computation
import Util.ICStringLen
import Util.DeepSeq
copyFile :: String -> String -> IO ()
copyFile source destination =
do
unitWE <- copyFileWE source destination
coerceWithErrorIO unitWE
copyFileWE :: String -> String -> IO (WithError ())
copyFileWE source destination =
if source == destination
then
return (hasValue ())
else
IOErr.catch (do
Dir.copyFile source destination
return(hasValue()))
(\ioErr ->
let
codeStr = if IOErr.isAlreadyExistsError ioErr
then ("Can't write to " ++ destination ++ ". File already exists!")
else if IOErr.isDoesNotExistError ioErr
then ("Can't read from " ++ source ++ ". File doesn't exists!")
else if IOErr.isPermissionError ioErr
then ("Can't write to " ++ destination ++ ". Insufficient permissions!")
else if IOErr.isFullError ioErr
then ("Can't write to " ++ destination ++ ". Disk full!")
else ("Something went wrong within copyFile.")
in
return(hasError codeStr)
)
copyFileToString :: FilePath -> IO String
copyFileToString filePath =
do
s <- IO.readFile filePath
s `deepSeq` (return s)
copyFileToStringCheck :: FilePath -> IO (WithError String)
copyFileToStringCheck filePath =
exceptionToError
(\ ioError ->
if IO.isDoesNotExistError ioError
then
Just "File does not exist"
else if IO.isAlreadyInUseError ioError
then
Just "File is already in use"
else if IO.isPermissionError ioError
then
Just "No read access to file"
else
Nothing
)
(copyFileToString filePath)
copyFileToCStringLen :: FilePath -> IO CStringLen
copyFileToCStringLen file =
do
str <- readFile file
newCStringLen $!! str
copyFileToICStringLenCheck :: FilePath -> IO (WithError ICStringLen)
copyFileToICStringLenCheck filePath =
exceptionToError
(\ ioError -> Just $ show (ioError :: IOException)
)
(copyFileToICStringLen filePath)
copyFileToICStringLen :: FilePath -> IO ICStringLen
copyFileToICStringLen filePath =
do
handle <- IO.openFile filePath IO.ReadMode
len <- IO.hFileSize handle
if len > fromIntegral (maxBound::Int)
then
error "CopyFile.copyFileToICStringLen: file too big"
else
do
let
len_i = fromIntegral len
mkICStringLen len_i
(\ cString ->
do
lenRead <- hGetBuf handle cString len_i
when (lenRead < len_i)
(error"EOF within CopyFile.copyFileToICStringLen")
)
copyICStringLenToFile :: ICStringLen -> FilePath -> IO ()
copyICStringLenToFile icsl filePath =
withICStringLen icsl (\ i cstr ->
copyCStringLenToFile (cstr,i) filePath
)
copyStringToFileCheck :: String -> FilePath -> IO (WithError ())
copyStringToFileCheck str filePath =
exceptionToError
(\ ioError -> Just $ show (ioError :: IOException)
)
(copyStringToFile str filePath)
copyStringToFile :: String -> FilePath -> IO ()
copyStringToFile str filePath =
withCStringLen str
(\ cStringLen -> copyCStringLenToFile cStringLen filePath)
copyCStringLenToFile :: CStringLen -> FilePath -> IO ()
copyCStringLenToFile (ptr,len) filePath =
do
handle <- IO.openFile filePath IO.WriteMode
hPutBuf handle ptr len
IO.hFlush handle