fix bugs and added mkdtemp
[packages/unix.git] / System / Posix / Temp.hsc
1 {-# LANGUAGE ForeignFunctionInterface #-}
2 #if __GLASGOW_HASKELL__ >= 701
3 {-# LANGUAGE Trustworthy #-}
4 #endif
5 -----------------------------------------------------------------------------
6 -- |
7 -- Module      :  System.Posix.Temp
8 -- Copyright   :  (c) Volker Stolz <vs@foldr.org>
9 -- License     :  BSD-style (see the file libraries/base/LICENSE)
10 --
11 -- Maintainer  :  vs@foldr.org
12 -- Stability   :  provisional
13 -- Portability :  non-portable (requires POSIX)
14 --
15 -- POSIX environment support
16 --
17 -----------------------------------------------------------------------------
18
19 module System.Posix.Temp (
20
21     mkstemp
22   , mkdtemp
23
24 {- Not ported (yet?):
25     tmpfile: can we handle FILE*?
26     tmpnam: ISO C, should go in base?
27     tempname: dito
28 -}
29
30 ) where
31
32 #include "HsUnix.h"
33
34 import System.IO
35 import System.Posix.IO
36 import System.Posix.Types
37 import System.Posix.Directory (createDirectory)
38 import Foreign.C
39
40 #if __GLASGOW_HASKELL__ > 700
41 import System.Posix.Internals (withFilePath, peekFilePath)
42 #elif __GLASGOW_HASKELL__ > 611
43 import System.Posix.Internals (withFilePath)
44
45 peekFilePath :: CString -> IO FilePath
46 peekFilePath = peekCString
47 #else
48 withFilePath :: FilePath -> (CString -> IO a) -> IO a
49 withFilePath = withCString
50
51 peekFilePath :: CString -> IO FilePath
52 peekFilePath = peekCString
53 #endif
54
55 -- |'mkstemp' - make a unique filename and open it for
56 -- reading\/writing (only safe on GHC & Hugs).
57 -- The returned 'FilePath' is the (possibly relative) path of
58 -- the created file, which is padded with 6 random characters.
59 mkstemp :: String -> IO (FilePath, Handle)
60 mkstemp template' = do
61   let template = template' ++ "XXXXXX"
62 #if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)
63   withFilePath template $ \ ptr -> do
64     fd <- throwErrnoIfMinus1 "mkstemp" (c_mkstemp ptr)
65     name <- peekFilePath ptr
66     h <- fdToHandle (Fd fd)
67     return (name, h)
68 #else
69   name <- mktemp template
70   h <- openFile name ReadWriteMode
71   return (name, h)
72 #endif
73
74 -- |'mkdtemp' - make a unique directory (only safe on GHC & Hugs).
75 -- The returned 'FilePath' is the path of the created directory,
76 -- which is padded with 6 random characters.
77 mkdtemp :: String -> IO FilePath
78 mkdtemp template' = do
79   let template = template' ++ "XXXXXX"
80 #if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)
81   withFilePath template $ \ ptr -> do
82     throwErrnoIfNull "mkdtemp" (c_mkdtemp ptr)
83     name <- peekFilePath ptr
84     return name
85 #else
86   name <- mktemp template
87   h <- createDirectory name (toEnum 0o700)
88   return name
89 #endif
90
91 #if !defined(__GLASGOW_HASKELL__) && !defined(__HUGS__)
92 -- |'mktemp' - make a unique file name
93 -- It is required that the template have six trailing \'X\'s.
94 -- This function should be considered deprecated
95 mktemp :: String -> IO String
96 mktemp template = do
97   withFilePath template $ \ ptr -> do
98     ptr <- throwErrnoIfNull "mktemp" (c_mktemp ptr)
99     peekFilePath ptr
100
101 foreign import ccall unsafe "mktemp"
102   c_mktemp :: CString -> IO CString
103 #endif
104
105 foreign import ccall unsafe "HsUnix.h __hscore_mkstemp"
106   c_mkstemp :: CString -> IO CInt
107
108 foreign import ccall unsafe "HsUnix.h __hscore_mkdtemp"
109   c_mkdtemp :: CString -> IO CString