{-# LANGUAGE CPP #-}
{-# LANGUAGE Safe #-}
module System.Path(
splitExt, absNormPath, secureAbsNormPath,
recurseDir, recurseDirStat, recursiveRemove,
bracketCWD,
mktmpdir, brackettmpdir, brackettmpdirCWD
)
where
import safe Data.List.Utils ( startswith, alwaysElemRIndex )
#if !(defined(mingw32_HOST_OS) || defined(mingw32_TARGET_OS) || defined(__MINGW32__))
import safe System.Directory
( getCurrentDirectory, removeFile, setCurrentDirectory )
import System.Posix.Directory (createDirectory)
import safe System.Posix.Temp ( mkstemp )
#else
import System.Directory
#endif
import safe Control.Exception ( finally )
import System.FilePath (pathSeparator)
import safe System.IO ( hClose )
import safe System.IO.HVFS.Utils
( SystemFS(SystemFS), recurseDir, recurseDirStat, recursiveRemove )
import safe System.Path.NameManip
( normalise_path, absolute_path_by, guess_dotdot )
splitExt :: String -> (String, String)
splitExt :: String -> (String, String)
splitExt String
path =
let dotindex :: Int
dotindex = Char -> String -> Int
forall a. Eq a => a -> [a] -> Int
alwaysElemRIndex Char
'.' String
path
slashindex :: Int
slashindex = Char -> String -> Int
forall a. Eq a => a -> [a] -> Int
alwaysElemRIndex Char
pathSeparator String
path
in
if Int
dotindex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
slashindex
then (String
path, String
"")
else ((Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
dotindex String
path), (Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
dotindex String
path))
absNormPath :: String
-> String
-> Maybe String
absNormPath :: String -> String -> Maybe String
absNormPath String
base String
thepath =
let path :: String
path = String -> String -> String
absolute_path_by String
base String
thepath
in case String -> Maybe String
guess_dotdot (String -> String
normalise_path String
path) of
Just String
"." -> String -> Maybe String
forall a. a -> Maybe a
Just [Char
pathSeparator]
Maybe String
x -> Maybe String
x
secureAbsNormPath :: String
-> String
-> Maybe String
secureAbsNormPath :: String -> String -> Maybe String
secureAbsNormPath String
base String
s = do String
p <- String -> String -> Maybe String
absNormPath String
base String
s
if String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
startswith String
base String
p
then String -> Maybe String
forall (m :: * -> *) a. Monad m => a -> m a
return String
p
else String -> Maybe String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
""
mktmpdir :: String -> IO String
#if !(defined(mingw32_HOST_OS) || defined(mingw32_TARGET_OS) || defined(__MINGW32__))
mktmpdir :: String -> IO String
mktmpdir String
x =
do (String, Handle)
y <- String -> IO (String, Handle)
mkstemp String
x
let (String
dirname, Handle
h) = (String, Handle)
y
Handle -> IO ()
hClose Handle
h
String -> IO ()
removeFile String
dirname
String -> FileMode -> IO ()
createDirectory String
dirname FileMode
0o700
String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
dirname
#else
mktmpdir x =
do (fp, h) <- openTempFile "" x
hClose h
removeFile fp
createDirectory fp
return fp
#endif
brackettmpdir :: String -> (String -> IO a) -> IO a
brackettmpdir :: String -> (String -> IO a) -> IO a
brackettmpdir String
x String -> IO a
action = do String
tmpdir <- String -> IO String
mktmpdir String
x
IO a -> IO () -> IO a
forall a b. IO a -> IO b -> IO a
finally (String -> IO a
action String
tmpdir)
(SystemFS -> String -> IO ()
forall a. HVFS a => a -> String -> IO ()
recursiveRemove SystemFS
SystemFS String
tmpdir)
bracketCWD :: FilePath -> IO a -> IO a
bracketCWD :: String -> IO a -> IO a
bracketCWD String
fp IO a
action =
do String
oldcwd <- IO String
getCurrentDirectory
String -> IO ()
setCurrentDirectory String
fp
IO a -> IO () -> IO a
forall a b. IO a -> IO b -> IO a
finally IO a
action (String -> IO ()
setCurrentDirectory String
oldcwd)
brackettmpdirCWD :: String -> IO a -> IO a
brackettmpdirCWD :: String -> IO a -> IO a
brackettmpdirCWD String
template IO a
action =
String -> (String -> IO a) -> IO a
forall a. String -> (String -> IO a) -> IO a
brackettmpdir String
template (\String
newdir -> String -> IO a -> IO a
forall a. String -> IO a -> IO a
bracketCWD String
newdir IO a
action)