module System.IO.Temp ( createTempDirectory , openBinaryTempFile , openTempFile ) where -- NB: this module was extracted directly from "Distribution/Simple/Utils.hs" -- in a Cabal tree whose most recent commit was on Sun Oct 10 22:00:26 -- -- The files in the Distribution/Compat tree are exact copies of the -- corresponding file in the Cabal checkout. import Control.Monad ( when ) import Control.Monad.IO.Class ( MonadIO(..) ) import Control.Monad.Trans.Resource ( MonadResource, ReleaseKey, allocate ) import System.Directory ( doesDirectoryExist, doesFileExist, getTemporaryDirectory , removeDirectory, removeDirectoryRecursive, removeFile ) import System.IO ( Handle ) import qualified Distribution.Compat.TempFile as Compat -- | Create a temporary directory. The directory will be deleted if empty -- when the resource is released. If a parent directory is supplied, the -- temporary directory will be created there; otherwise, it will be created -- in the system temporary directory returned by 'getTemporaryDirectory'. createTempDirectory :: MonadResource m => Maybe FilePath -- ^ optional parent directory -> String -- ^ filename template; for security, a random number -- will be inserted between the filename and any -- extension. -> m (ReleaseKey, FilePath) createTempDirectory mDir tmpl = do dir <- resolveTempDir mDir allocate (Compat.createTempDirectory dir tmpl) removeDirectoryRecursive -- | Open a temporary file in binary mode. The file will be readable and -- writeable, but only by the current user. The file will be deleted when -- the resource is released, if it still exists. If a parent directory is -- supplied, the file will be created there; otherwise, it will be created -- in the system temporary directory returned by 'getTemporaryDirectory'. openBinaryTempFile :: MonadResource m => Maybe FilePath -- ^ optional parent directory -> String -- ^ filename template; for security, a random number -- will be inserted between the filename and any -- extension. -> m (ReleaseKey, FilePath, Handle) openBinaryTempFile mDir tmpl = do dir <- resolveTempDir mDir (key, (path, h)) <- allocate (Compat.openBinaryTempFile dir tmpl) (removeFileIfExists . fst) return (key, path, h) -- | Open a temporary file. The file will be readable and writeable, but -- only by the current user. The file will be deleted when the resource is -- released, if it still exists. If a parent directory is supplied, the -- file will be created there; otherwise, it will be created in the system -- temporary directory returned by 'getTemporaryDirectory'. openTempFile :: MonadResource m => Maybe FilePath -- ^ optional parent directory -> String -- ^ filename template; for security, a random number will be -- inserted between the filename and any extension. -> m (ReleaseKey, FilePath, Handle) openTempFile mDir tmpl = do dir <- resolveTempDir mDir (key, (path, h)) <- allocate (Compat.openTempFile dir tmpl) (removeFileIfExists . fst) return (key, path, h) removeFileIfExists :: FilePath -> IO () removeFileIfExists path = do exists <- doesFileExist path when exists $ removeFile path resolveTempDir :: MonadIO m => Maybe FilePath -> m FilePath resolveTempDir = maybe (liftIO getTemporaryDirectory) return