diff --git a/src/HSFM/FileSystem/FileOperations.hs b/src/HSFM/FileSystem/FileOperations.hs index 7f535b7..8638ca0 100644 --- a/src/HSFM/FileSystem/FileOperations.hs +++ b/src/HSFM/FileSystem/FileOperations.hs @@ -184,7 +184,7 @@ data FileType = Directory | CharacterDevice | NamedPipe | Socket - deriving (Show) + deriving (Eq, Show) @@ -614,6 +614,13 @@ getDirsFiles p = --------------------------- +-- |Get the file type of the file located at the given path. Does +-- not follow symbolic links. +-- +-- Throws: +-- +-- - `NoSuchThing` if the file does not exist +-- - `PermissionDenied` if any part of the path is not accessible getFileType :: Path Abs -> IO FileType getFileType p = do fs <- PF.getSymbolicLinkStatus (P.fromAbs p) diff --git a/test/Spec.hs b/test/Spec.hs index 2526346..eb746c0 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -42,6 +42,7 @@ import System.Posix.Files.ByteString + -- TODO: chardev, blockdev, namedpipe, socket @@ -53,10 +54,11 @@ main = hspec $ before_ fixPermissions $ after_ revertPermissions $ do , createRegularFileSpec , renameFileSpec , moveFileSpec - ,recreateSymlinkSpec + , recreateSymlinkSpec + , getFileTypeSpec ] - -- run all tests twice to catch missing cleanups or state skew + -- run all stateful tests twice to catch missing cleanups or state skew sequence_ tests sequence_ tests @@ -77,6 +79,7 @@ main = hspec $ before_ fixPermissions $ after_ revertPermissions $ do ,"test/renameFile/noPerms" ,"test/moveFile/noPerms" ,"test/recreateSymlinkSpec/noPerms" + ,"test/getFileTypeSpec/noPerms" ] fixPermissions = do sequence_ $ fmap noWritableDirPerms noWriteDirs @@ -489,6 +492,49 @@ recreateSymlinkSpec = (\e -> ioeGetErrorType e == AlreadyExists) +getFileTypeSpec :: Spec +getFileTypeSpec = + describe "HSFM.FileSystem.FileOperations.getFileType" $ do + + -- successes -- + it "getFileType, regular file" $ + getFileType' "test/getFileTypeSpec/regularfile" + `shouldReturn` RegularFile + + it "getFileType, directory" $ + getFileType' "test/getFileTypeSpec/directory" + `shouldReturn` Directory + + it "getFileType, directory with null permissions" $ + getFileType' "test/getFileTypeSpec/noPerms" + `shouldReturn` Directory + + it "getFileType, symlink to file" $ + getFileType' "test/getFileTypeSpec/symlink" + `shouldReturn` SymbolicLink + + it "getFileType, symlink to directory" $ + getFileType' "test/getFileTypeSpec/symlinkD" + `shouldReturn` SymbolicLink + + it "getFileType, broken symlink" $ + getFileType' "test/getFileTypeSpec/brokenSymlink" + `shouldReturn` SymbolicLink + + -- posix failures -- + it "getFileType, file does not exist" $ + getFileType' "test/getFileTypeSpec/nothingHere" + `shouldThrow` + (\e -> ioeGetErrorType e == NoSuchThing) + + it "getFileType, can't open directory" $ + getFileType' "test/getFileTypeSpec/noPerms/forz" + `shouldThrow` + (\e -> ioeGetErrorType e == PermissionDenied) + + + + ----------------- --[ Utilities ]-- @@ -597,3 +643,9 @@ normalDirPerms path = do file <- (pwd P.) <$> P.parseRel path setFileMode (P.fromAbs file) newDirPerms + +getFileType' :: ByteString -> IO FileType +getFileType' path = do + pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs + file <- (pwd P.) <$> P.parseRel path + getFileType file diff --git a/test/getFileTypeSpec/brokenSymlink b/test/getFileTypeSpec/brokenSymlink new file mode 120000 index 0000000..86a410d --- /dev/null +++ b/test/getFileTypeSpec/brokenSymlink @@ -0,0 +1 @@ +broken \ No newline at end of file diff --git a/test/getFileTypeSpec/directory/.keep b/test/getFileTypeSpec/directory/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/getFileTypeSpec/noPerms/.keep b/test/getFileTypeSpec/noPerms/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/getFileTypeSpec/regularfile b/test/getFileTypeSpec/regularfile new file mode 100644 index 0000000..e69de29 diff --git a/test/getFileTypeSpec/symlink b/test/getFileTypeSpec/symlink new file mode 120000 index 0000000..6a33ade --- /dev/null +++ b/test/getFileTypeSpec/symlink @@ -0,0 +1 @@ +regularfile \ No newline at end of file diff --git a/test/getFileTypeSpec/symlinkD b/test/getFileTypeSpec/symlinkD new file mode 120000 index 0000000..6d0450c --- /dev/null +++ b/test/getFileTypeSpec/symlinkD @@ -0,0 +1 @@ +directory \ No newline at end of file