From 6a1f80bc17bfc9debccde0b3d7a2b684775d0f61 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Mon, 13 Jan 2020 23:12:55 +0100 Subject: [PATCH] Move file check functions to HPath.IO --- hpath-io/hpath-io.cabal | 1 - hpath-io/src/HPath/IO.hs | 84 ++++++++++++++++++++++++++++++++- hpath-io/src/HPath/IO.hs-boot | 8 ++++ hpath-io/src/HPath/IO/Errors.hs | 44 ++--------------- 4 files changed, 94 insertions(+), 43 deletions(-) diff --git a/hpath-io/hpath-io.cabal b/hpath-io/hpath-io.cabal index 1f02815..4072b96 100644 --- a/hpath-io/hpath-io.cabal +++ b/hpath-io/hpath-io.cabal @@ -73,7 +73,6 @@ test-suite spec HPath.IO.GetFileTypeSpec HPath.IO.MoveFileOverwriteSpec HPath.IO.MoveFileSpec - HPath.IO.ReadFileEOFSpec HPath.IO.ReadFileSpec HPath.IO.RecreateSymlinkOverwriteSpec HPath.IO.RecreateSymlinkSpec diff --git a/hpath-io/src/HPath/IO.hs b/hpath-io/src/HPath/IO.hs index ff6826d..c6ef399 100644 --- a/hpath-io/src/HPath/IO.hs +++ b/hpath-io/src/HPath/IO.hs @@ -73,6 +73,12 @@ module HPath.IO -- * File permissions , newFilePerms , newDirPerms + -- * File checks + , doesExist + , doesFileExist + , doesDirectoryExist + , isWritable + , canOpenDirectory -- * Directory reading , getDirsFiles -- * Filetype operations @@ -191,7 +197,9 @@ import System.Posix.ByteString import System.Posix.Directory.ByteString ( createDirectory + , closeDirStream , getWorkingDirectory + , openDirStream , removeDirectory ) import System.Posix.Directory.Traversals @@ -201,6 +209,7 @@ import System.Posix.Directory.Traversals import System.Posix.Files.ByteString ( createSymbolicLink + , fileAccess , fileMode , getFdStatus , groupExecuteMode @@ -446,7 +455,9 @@ recreateSymlink symsource@(MkPath symsourceBS) newsym@(MkPath newsymBS) cm case cm of Strict -> return () Overwrite -> do - writable <- toAbs newsym >>= isWritable + writable <- toAbs newsym >>= (\p -> do + e <- doesExist p + if e then isWritable p else pure False) isfile <- doesFileExist newsym isdir <- doesDirectoryExist newsym when (writable && isfile) (deleteFile newsym) @@ -830,7 +841,10 @@ moveFile from to cm = do easyDelete from Overwrite -> do ft <- getFileType from - writable <- toAbs to >>= isWritable + writable <- toAbs to >>= (\p -> do + e <- doesFileExist p + if e then isWritable p else pure False) + case ft of RegularFile -> do exists <- doesFileExist to @@ -980,6 +994,72 @@ newDirPerms + + ------------------- + --[ File checks ]-- + ------------------- + + +-- |Checks if the given file exists. +-- Does not follow symlinks. +-- +-- Only eNOENT is catched (and returns False). +doesExist :: Path b -> IO Bool +doesExist (MkPath bs) = + catchErrno [eNOENT] (do + _ <- PF.getSymbolicLinkStatus bs + return $ True) + $ return False + + +-- |Checks if the given file exists and is not a directory. +-- Does not follow symlinks. +-- +-- Only eNOENT is catched (and returns False). +doesFileExist :: Path b -> IO Bool +doesFileExist (MkPath bs) = + catchErrno [eNOENT] (do + fs <- PF.getSymbolicLinkStatus bs + return $ not . PF.isDirectory $ fs) + $ return False + + +-- |Checks if the given file exists and is a directory. +-- Does not follow symlinks. +-- +-- Only eNOENT is catched (and returns False). +doesDirectoryExist :: Path b -> IO Bool +doesDirectoryExist (MkPath bs) = + catchErrno [eNOENT] (do + fs <- PF.getSymbolicLinkStatus bs + return $ PF.isDirectory fs) + $ return False + + +-- |Checks whether a file or folder is writable. +-- +-- Only eACCES, eROFS, eTXTBSY, ePERM are catched (and return False). +-- +-- Throws: +-- +-- - `NoSuchThing` if the file does not exist +isWritable :: Path b -> IO Bool +isWritable (MkPath bs) = fileAccess bs False True False + + +-- |Checks whether the directory at the given path exists and can be +-- opened. This invokes `openDirStream` which follows symlinks. +canOpenDirectory :: Path b -> IO Bool +canOpenDirectory (MkPath bs) = + handleIOError (\_ -> return False) $ do + bracket (openDirStream bs) + closeDirStream + (\_ -> return ()) + return True + + + + ------------------------- --[ Directory reading ]-- ------------------------- diff --git a/hpath-io/src/HPath/IO.hs-boot b/hpath-io/src/HPath/IO.hs-boot index d16bf75..bee74f5 100644 --- a/hpath-io/src/HPath/IO.hs-boot +++ b/hpath-io/src/HPath/IO.hs-boot @@ -6,3 +6,11 @@ import HPath canonicalizePath :: Path b -> IO (Path Abs) toAbs :: Path b -> IO (Path Abs) + +doesFileExist :: Path b -> IO Bool + +doesDirectoryExist :: Path b -> IO Bool + +isWritable :: Path b -> IO Bool + +canOpenDirectory :: Path b -> IO Bool diff --git a/hpath-io/src/HPath/IO/Errors.hs b/hpath-io/src/HPath/IO/Errors.hs index f6ef440..4668c52 100644 --- a/hpath-io/src/HPath/IO/Errors.hs +++ b/hpath-io/src/HPath/IO/Errors.hs @@ -33,10 +33,6 @@ module HPath.IO.Errors , throwSameFile , sameFile , throwDestinationInSource - , doesFileExist - , doesDirectoryExist - , isWritable - , canOpenDirectory -- * Error handling functions , catchErrno @@ -92,6 +88,10 @@ import {-# SOURCE #-} HPath.IO ( canonicalizePath , toAbs + , doesFileExist + , doesDirectoryExist + , isWritable + , canOpenDirectory ) import System.IO.Error ( @@ -242,42 +242,6 @@ throwDestinationInSource (MkPath sbs) dest@(MkPath dbs) = do (throwIO $ DestinationInSource dbs sbs) --- |Checks if the given file exists and is not a directory. --- Does not follow symlinks. -doesFileExist :: Path b -> IO Bool -doesFileExist (MkPath bs) = - handleIOError (\_ -> return False) $ do - fs <- PF.getSymbolicLinkStatus bs - return $ not . PF.isDirectory $ fs - - --- |Checks if the given file exists and is a directory. --- Does not follow symlinks. -doesDirectoryExist :: Path b -> IO Bool -doesDirectoryExist (MkPath bs) = - handleIOError (\_ -> return False) $ do - fs <- PF.getSymbolicLinkStatus bs - return $ PF.isDirectory fs - - --- |Checks whether a file or folder is writable. -isWritable :: Path b -> IO Bool -isWritable (MkPath bs) = - handleIOError (\_ -> return False) $ - fileAccess bs False True False - - --- |Checks whether the directory at the given path exists and can be --- opened. This invokes `openDirStream` which follows symlinks. -canOpenDirectory :: Path b -> IO Bool -canOpenDirectory (MkPath bs) = - handleIOError (\_ -> return False) $ do - bracket (PFD.openDirStream bs) - PFD.closeDirStream - (\_ -> return ()) - return True - - --------------------------------