1 {-# OPTIONS_GHC -cpp #-}
4 module Workaround
( renameFile, setExecutable
, getCurrentDirectory,
5 installHandler
, raiseSignal
, Handler
(..), Signal
,
6 sigINT
, sigHUP
, sigABRT
, sigALRM
, sigTERM
, sigPIPE
) where
9 import System
.Posix
.Signals
(installHandler
, raiseSignal
, Handler
(..), Signal
,
10 sigINT
, sigHUP
, sigABRT
, sigALRM
, sigTERM
, sigPIPE
,)
14 import qualified System
.Directory
( renameFile, getCurrentDirectory, removeFile )
15 import qualified Control
.Exception
( block
)
16 import qualified System
.IO.Error
( isDoesNotExistError, ioError, catch )
18 import System
.Directory
( renameFile, getCurrentDirectory )
19 import System
.Posix
.Files
(fileMode
,getFileStatus
, setFileMode
,
21 ownerReadMode
, ownerWriteMode
, ownerExecuteMode
,
22 groupReadMode
, groupWriteMode
, groupExecuteMode
,
23 otherReadMode
, otherWriteMode
, otherExecuteMode
)
24 import Data
.Bits
( (.&.), (.|
.), complement
)
28 -- Dummy implementation of POSIX signals
29 data Handler
= Default | Ignore | Catch
(IO ())
32 installHandler
:: Signal
-> Handler
-> Maybe () -> IO ()
33 installHandler _ _ _
= return ()
35 raiseSignal
:: Signal
-> IO ()
36 raiseSignal _
= return ()
38 sigINT
, {- sigKILL, -} sigHUP
, {- sigQUIT, -} sigABRT
, sigALRM
, sigTERM
, sigPIPE
:: Signal
40 -- not used: sigKILL = 0
42 -- not used: sigQUIT = 0
51 System.Directory.renameFile incorrectly fails when the new file already
52 exists. This code works around that bug at the cost of losing atomic
56 renameFile :: FilePath -> FilePath -> IO ()
57 renameFile old new
= Control
.Exception
.block
$
58 System
.Directory
.renameFile old new
59 `System
.IO.Error
.catch`
\_
->
60 do System
.Directory
.removeFile new
61 `System
.IO.Error
.catch`
62 (\e
-> if System
.IO.Error
.isDoesNotExistError e
64 else System
.IO.Error
.ioError e
)
65 System
.Directory
.renameFile old new
67 setExecutable
:: FilePath -> Bool -> IO ()
68 setExecutable _ _
= return ()
71 System.Directory.getCurrentDirectory returns a path with backslashes in it
72 under windows, and some of the code gets confused by that, so we override
73 getCurrentDirectory and translates '\\' to '/'
76 getCurrentDirectory :: IO FilePath
77 getCurrentDirectory = do d
<- System
.Directory
.getCurrentDirectory
84 setExecutable
:: FilePath -> Bool -> IO ()
86 do st
<- getFileStatus f
87 umask
<- setFileCreationMask
0
88 setFileCreationMask umask
89 let rw
= fileMode st
.&.
90 (ownerReadMode
.|
. ownerWriteMode
.|
.
91 groupReadMode
.|
. groupWriteMode
.|
.
92 otherReadMode
.|
. otherWriteMode
)
93 total
= if ex
then rw
.|
.
94 ((ownerExecuteMode
.|
. groupExecuteMode
.|
. otherExecuteMode
)