module System.IO.SafeWrite
( withOutputFile
, syncFile
) where
import System.FilePath (takeDirectory)
import System.Posix.IO (openFd, defaultFileFlags, closeFd, OpenMode(..))
import System.Posix.Unistd (fileSynchronise)
import Control.Exception (bracket, onException)
import System.IO (Handle, hClose, openTempFile)
import System.Directory (renameFile, removeFile)
syncFile :: FilePath
-> IO ()
syncFile fname = do
bracket (openFd fname ReadWrite Nothing defaultFileFlags)
closeFd
fileSynchronise
bracket (openFd (takeDirectory fname) ReadOnly Nothing defaultFileFlags)
closeFd
fileSynchronise
withOutputFile ::
FilePath
-> (Handle -> IO a)
-> IO a
withOutputFile finalname act = do
(tname, th) <- openTempFile (takeDirectory finalname) finalname
(do
r <- act th
hClose th
syncFile tname
renameFile tname finalname
return r) `onException` (hClose th >> removeFile tname)