X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=System%2FDirectory.hs;h=d1cf49518ef9d0e5af8a801bc09aaa83b74cf176;hb=1f9af202c6e595283fe57577eade9b8b4c30355c;hp=fcdb937916240718d625f8f04562348e3736cfde;hpb=1b72414cedb0fc9f723f23ccced5526496bde138;p=haskell-directory.git diff --git a/System/Directory.hs b/System/Directory.hs index fcdb937..d1cf495 100644 --- a/System/Directory.hs +++ b/System/Directory.hs @@ -70,12 +70,14 @@ import Prelude hiding ( catch ) import System.Environment ( getEnv ) import System.FilePath +import System.IO import System.IO.Error hiding ( catch, try ) import Control.Monad ( when, unless ) import Control.Exception #ifdef __NHC__ import Directory +import System (system) #endif /* __NHC__ */ #ifdef __HUGS__ @@ -91,7 +93,6 @@ import Foreign.C import System.Posix.Types import System.Posix.Internals import System.Time ( ClockTime(..) ) -import System.IO import GHC.IOBase ( IOException(..), IOErrorType(..), ioException ) @@ -100,7 +101,7 @@ A directory contains a series of entries, each of which is a named reference to a file system object (file, directory etc.). Some entries may be hidden, inaccessible, or have some administrative function (e.g. `.' or `..' under POSIX -), but in +), but in this standard all such entries are considered to form part of the directory contents. Entries in sub-directories are not, however, considered to form part of the directory contents. @@ -154,6 +155,29 @@ The operation may fail with: getPermissions :: FilePath -> IO Permissions getPermissions name = do withCString name $ \s -> do +#ifdef mingw32_HOST_OS + -- stat() does a better job of guessing the permissions on Windows + -- than access() does. e.g. for execute permission, it looks at the + -- filename extension :-) + -- + -- I tried for a while to do this properly, using the Windows security API, + -- and eventually gave up. getPermissions is a flawed API anyway. -- SimonM + allocaBytes sizeof_stat $ \ p_stat -> do + throwErrnoIfMinus1_ "getPermissions" $ c_stat s p_stat + mode <- st_mode p_stat + let read = mode .&. s_IRUSR + let write = mode .&. s_IWUSR + let exec = mode .&. s_IXUSR + let is_dir = mode .&. s_IFDIR + return ( + Permissions { + readable = read /= 0, + writable = write /= 0, + executable = is_dir == 0 && exec /= 0, + searchable = is_dir /= 0 && exec /= 0 + } + ) +#else read <- c_access s r_OK write <- c_access s w_OK exec <- c_access s x_OK @@ -167,6 +191,7 @@ getPermissions name = do searchable = is_dir && exec == 0 } ) +#endif {- |The 'setPermissions' operation sets the permissions for the file or directory. @@ -513,6 +538,12 @@ copied to /new/, if possible. -} copyFile :: FilePath -> FilePath -> IO () +#ifdef __NHC__ +copyFile fromFPath toFPath = + do readFile fromFPath >>= writeFile toFPath + try (copyPermissions fromFPath toFPath) + return () +#else copyFile fromFPath toFPath = copy `catch` (\e -> case e of IOException e -> @@ -522,7 +553,7 @@ copyFile fromFPath toFPath = bracketOnError openTmp cleanTmp $ \(tmpFPath, hTmp) -> do allocaBytes bufferSize $ copyContents hFrom hTmp hClose hTmp - try (copyPermissions fromFPath toFPath) + try (copyPermissions fromFPath tmpFPath) renameFile tmpFPath toFPath openTmp = openBinaryTempFile (takeDirectory toFPath) ".copyFile.tmp" cleanTmp (tmpFPath, hTmp) = do try $ hClose hTmp @@ -534,6 +565,7 @@ copyFile fromFPath toFPath = when (count > 0) $ do hPutBuf hTo buffer count copyContents hFrom hTo buffer +#endif -- | Given path referring to a file or directory, returns a -- canonicalized path, with the intent that two paths referring @@ -552,7 +584,9 @@ canonicalizePath fpath = #else do c_realpath pInPath pOutPath #endif - peekCString pOutPath + path <- peekCString pOutPath + return (normalise path) + -- normalise does more stuff, like upper-casing the drive letter #if defined(mingw32_HOST_OS) foreign import stdcall unsafe "GetFullPathNameA" @@ -841,6 +875,7 @@ foreign import ccall unsafe "__hscore_X_OK" x_OK :: CInt foreign import ccall unsafe "__hscore_S_IRUSR" s_IRUSR :: CMode foreign import ccall unsafe "__hscore_S_IWUSR" s_IWUSR :: CMode foreign import ccall unsafe "__hscore_S_IXUSR" s_IXUSR :: CMode +foreign import ccall unsafe "__hscore_S_IFDIR" s_IFDIR :: CMode foreign import ccall unsafe "__hscore_long_path_size" long_path_size :: Int @@ -992,7 +1027,14 @@ getTemporaryDirectory = do r <- c_GetTempPath (fromIntegral long_path_size) pPath peekCString pPath #else - catch (getEnv "TMPDIR") (\ex -> return "/tmp") + getEnv "TMPDIR" +#if !__NHC__ + `catch` \ex -> case ex of + IOException e | isDoesNotExistError e -> return "/tmp" + _ -> throw ex +#else + `catch` (\ex -> return "/tmp") +#endif #endif #if defined(mingw32_HOST_OS)