{-# OPTIONS -cpp #-} -- #hide module Distribution.Compat.TempFile (openTempFile, withTempFile) where import System.IO (openFile, Handle, IOMode(ReadWriteMode)) import System.Directory (doesFileExist, removeFile) import Control.Exception (finally,try) import System.FilePath ( (), (<.>) ) #if (__GLASGOW_HASKELL__ || __HUGS__) import System.Posix.Internals (c_getpid) #else import System.Posix.Types (CPid(..)) #endif -- ------------------------------------------------------------ -- * temporary files -- ------------------------------------------------------------ -- TODO: this function *really really really* should be -- eliminated and replaced with System.IO.openTempFile, -- except that is currently GHC-only for no valid reason. -- use a temporary filename that doesn't already exist. -- NB. *not* secure (we don't atomically lock the tmp file we get) openTempFile :: FilePath -> String -> IO (FilePath, Handle) openTempFile tmp_dir template = do x <- getProcessID findTempName x where findTempName x = do let filename = template ++ show x path = tmp_dir filename b <- doesFileExist path if b then findTempName (x+1) else do hnd <- openFile path ReadWriteMode return (path, hnd) #if !(__GLASGOW_HASKELL__ || __HUGS__) foreign import ccall unsafe "getpid" c_getpid :: IO CPid #endif getProcessID :: IO Int getProcessID = c_getpid >>= return . fromIntegral -- use a temporary filename that doesn't already exist. -- NB. *not* secure (we don't atomically lock the tmp file we get) withTempFile :: FilePath -> String -> (FilePath -> IO a) -> IO a withTempFile tmp_dir extn action = do x <- getProcessID findTempName x where findTempName x = do let filename = ("tmp" ++ show x) <.> extn path = tmp_dir filename b <- doesFileExist path if b then findTempName (x+1) else action path `finally` try (removeFile path)