{-# LANGUAGE CPP #-} {-# OPTIONS_HADDOCK hide #-} module Distribution.Compat.Internal.TempFile ( openTempFile , openBinaryTempFile , openNewBinaryFile , createTempDirectory ) where import Distribution.Compat.Exception import GHC.IORef (IORef, atomicModifyIORef'_, newIORef) import System.FilePath ((</>)) import System.IO (Handle, openBinaryTempFile, openBinaryTempFileWithDefaultPermissions, openTempFile) import System.IO.Error (isAlreadyExistsError) import System.IO.Unsafe (unsafePerformIO) import System.Posix.Internals (c_getpid) #if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS) import System.Directory ( createDirectory ) #else import qualified System.Posix #endif openNewBinaryFile :: FilePath -> String -> IO (FilePath, Handle) openNewBinaryFile :: FilePath -> FilePath -> IO (FilePath, Handle) openNewBinaryFile = FilePath -> FilePath -> IO (FilePath, Handle) openBinaryTempFileWithDefaultPermissions createTempDirectory :: FilePath -> String -> IO FilePath createTempDirectory :: FilePath -> FilePath -> IO FilePath createTempDirectory FilePath dir FilePath template = do pid <- IO CPid c_getpid let findTempName = do (counter, _) <- IORef Word -> (Word -> Word) -> IO (Word, Word) forall a. IORef a -> (a -> a) -> IO (a, a) atomicModifyIORef'_ IORef Word tempDirectoryCounter (Word -> Word -> Word forall a. Num a => a -> a -> a + Word 1) let relpath = FilePath template FilePath -> FilePath -> FilePath forall a. [a] -> [a] -> [a] ++ FilePath "-" FilePath -> FilePath -> FilePath forall a. [a] -> [a] -> [a] ++ CPid -> FilePath forall a. Show a => a -> FilePath show CPid pid FilePath -> FilePath -> FilePath forall a. [a] -> [a] -> [a] ++ Word -> FilePath forall a. Show a => a -> FilePath show Word counter dirpath = FilePath dir FilePath -> FilePath -> FilePath </> FilePath relpath r <- tryIO $ mkPrivateDir dirpath case r of Right () _ -> FilePath -> IO FilePath forall a. a -> IO a forall (f :: * -> *) a. Applicative f => a -> f a pure FilePath relpath Left IOException e | IOException -> Bool isAlreadyExistsError IOException e -> IO FilePath findTempName | Bool otherwise -> IOException -> IO FilePath forall a. HasCallStack => IOException -> IO a ioError IOException e findTempName tempDirectoryCounter :: IORef Word tempDirectoryCounter :: IORef Word tempDirectoryCounter = IO (IORef Word) -> IORef Word forall a. IO a -> a unsafePerformIO (IO (IORef Word) -> IORef Word) -> IO (IORef Word) -> IORef Word forall a b. (a -> b) -> a -> b $ Word -> IO (IORef Word) forall a. a -> IO (IORef a) newIORef Word 0 {-# NOINLINE tempDirectoryCounter #-} mkPrivateDir :: String -> IO () #if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS) mkPrivateDir s = createDirectory s #else mkPrivateDir :: FilePath -> IO () mkPrivateDir FilePath s = FilePath -> FileMode -> IO () System.Posix.createDirectory FilePath s FileMode 0o700 #endif