[commit: packages/directory] master: Add isSymbolicLink (28b981d)
git at git.haskell.org
git at git.haskell.org
Sat Apr 16 19:13:26 UTC 2016
Repository : ssh://git@git.haskell.org/directory
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/28b981db6354e575e342477fd8ecd1ce1ea6cacd/directory
>---------------------------------------------------------------
commit 28b981db6354e575e342477fd8ecd1ce1ea6cacd
Author: Phil Ruffwind <rf at rufflewind.com>
Date: Thu Apr 14 05:33:58 2016 -0400
Add isSymbolicLink
>---------------------------------------------------------------
28b981db6354e575e342477fd8ecd1ce1ea6cacd
System/Directory.hs | 34 ++++++++++++++++++++++++++++------
changelog.md | 2 ++
directory.cabal | 1 +
tests/IsSymbolicLink.hs | 23 +++++++++++++++++++++++
tests/Main.hs | 2 ++
5 files changed, 56 insertions(+), 6 deletions(-)
diff --git a/System/Directory.hs b/System/Directory.hs
index 7e5edb1..ef97bcd 100644
--- a/System/Directory.hs
+++ b/System/Directory.hs
@@ -66,6 +66,9 @@ module System.Directory
, doesFileExist
, doesDirectoryExist
+ -- * Symbolic links
+ , isSymbolicLink
+
-- * Permissions
-- $permissions
@@ -487,12 +490,15 @@ getDirectoryType :: FilePath -> IO DirectoryType
getDirectoryType path =
(`ioeSetLocation` "getDirectoryType") `modifyIOError` do
#ifdef mingw32_HOST_OS
- classify <$> Win32.getFileAttributes path
- where fILE_ATTRIBUTE_REPARSE_POINT = 0x400
- classify attr
- | attr .&. Win32.fILE_ATTRIBUTE_DIRECTORY == 0 = NotDirectory
- | attr .&. fILE_ATTRIBUTE_REPARSE_POINT == 0 = Directory
- | otherwise = DirectoryLink
+ isDir <- withFileStatus "getDirectoryType" name isDirectory
+ if isDir
+ then do
+ isLink <- isSymbolicLink path
+ if isLink
+ then return DirectoryLink
+ else return Directory
+ else do
+ return NotDirectory
#else
stat <- Posix.getSymbolicLinkStatus path
return $ if Posix.isDirectory stat
@@ -1386,6 +1392,22 @@ doesFileExist name =
#endif
`catchIOError` \ _ -> return False
+-- | Check whether the path refers to a symbolic link. On Windows, this tests
+-- for @FILE_ATTRIBUTE_REPARSE_POINT at .
+--
+-- @since 1.2.6.0
+isSymbolicLink :: FilePath -> IO Bool
+isSymbolicLink path =
+ (`ioeSetLocation` "getDirectoryType") `modifyIOError` do
+#ifdef mingw32_HOST_OS
+ isReparsePoint <$> Win32.getFileAttributes path
+ where
+ fILE_ATTRIBUTE_REPARSE_POINT = 0x400
+ isReparsePoint attr = attr .&. fILE_ATTRIBUTE_REPARSE_POINT /= 0
+#else
+ Posix.isSymbolicLink <$> Posix.getSymbolicLinkStatus path
+#endif
+
#ifdef mingw32_HOST_OS
-- | Open the handle of an existing file or directory.
openFileHandle :: String -> Win32.AccessMode -> IO Win32.HANDLE
diff --git a/changelog.md b/changelog.md
index f917252..d047bd4 100644
--- a/changelog.md
+++ b/changelog.md
@@ -15,6 +15,8 @@ Changelog for the [`directory`][1] package
* Improve error message of `removeDirectoryRecursive` when used on a
directory symbolic link on Windows.
+ * Add `isSymbolicLink`
+
## 1.2.5.1 (February 2015)
* Improve error message of `getCurrentDirectory` when the current working
diff --git a/directory.cabal b/directory.cabal
index 3af7a70..8fc1a40 100644
--- a/directory.cabal
+++ b/directory.cabal
@@ -100,6 +100,7 @@ test-suite test
GetDirContents002
GetHomeDirectory001
GetPermissions001
+ IsSymbolicLink
RemoveDirectoryRecursive001
RenameFile001
Safe
diff --git a/tests/IsSymbolicLink.hs b/tests/IsSymbolicLink.hs
new file mode 100644
index 0000000..3f39e55
--- /dev/null
+++ b/tests/IsSymbolicLink.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE CPP #-}
+module IsSymbolicLink where
+#include "util.inl"
+import System.Directory
+import Control.Monad (when)
+#ifdef mingw32_HOST_OS
+import System.IO.Error (catchIOError, isPermissionError)
+#endif
+import TestUtils
+
+main :: TestEnv -> IO ()
+main _t = do
+ success <- (createSymbolicLink "x" "y" >> return True)
+#ifdef mingw32_HOST_OS
+ -- only test if symbolic links can be created
+ -- (usually disabled on Windows by group policy)
+ `catchIOError` \ e ->
+ if isPermissionError e
+ then return False
+ else ioError e
+#endif
+ when success $
+ T(expect) () =<< isSymbolicLink "y"
diff --git a/tests/Main.hs b/tests/Main.hs
index 19c6c28..65127f6 100644
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -15,6 +15,7 @@ import qualified GetDirContents001
import qualified GetDirContents002
import qualified GetHomeDirectory001
import qualified GetPermissions001
+import qualified IsSymbolicLink
import qualified RemoveDirectoryRecursive001
import qualified RenameFile001
import qualified Safe
@@ -38,6 +39,7 @@ main = T.testMain $ \ _t -> do
T.isolatedRun _t "GetDirContents002" GetDirContents002.main
T.isolatedRun _t "GetHomeDirectory001" GetHomeDirectory001.main
T.isolatedRun _t "GetPermissions001" GetPermissions001.main
+ T.isolatedRun _t "IsSymbolicLink" IsSymbolicLink.main
T.isolatedRun _t "RemoveDirectoryRecursive001" RemoveDirectoryRecursive001.main
T.isolatedRun _t "RenameFile001" RenameFile001.main
T.isolatedRun _t "Safe" Safe.main
More information about the ghc-commits
mailing list