{-# OPTIONS_GHC -Wno-redundant-constraints #-}
module Effectful.PosixCompat.Files.Static
(
PosixCompatFiles,
setFileMode,
setFdMode,
setFileCreationMask,
fileAccess,
fileExist,
getFileStatus,
getFdStatus,
getSymbolicLinkStatus,
createNamedPipe,
createDevice,
createLink,
removeLink,
createSymbolicLink,
readSymbolicLink,
rename,
setOwnerAndGroup,
setFdOwnerAndGroup,
setSymbolicLinkOwnerAndGroup,
setFileTimes,
touchFile,
setFileSize,
setFdSize,
getPathVar,
getFdPathVar,
runPosixFilesCompat,
PathType (..),
displayPathType,
throwIfWrongPathType,
isPathType,
getPathType,
)
where
import Control.Monad (unless)
import Data.Functor ((<&>))
import Effectful
( Dispatch (Static),
DispatchOf,
Eff,
Effect,
IOE,
type (:>),
)
import Effectful.Dispatch.Static
( HasCallStack,
SideEffects (WithSideEffects),
StaticRep,
evalStaticRep,
unsafeEff_,
)
import FileSystem.IO qualified as FS.IO
import FileSystem.PathType
( PathType
( PathTypeDirectory,
PathTypeFile,
PathTypeOther,
PathTypeSymbolicLink
),
displayPathType,
)
import GHC.IO.Exception (IOErrorType (InappropriateType))
import System.PosixCompat.Files (FileStatus, PathVar)
import System.PosixCompat.Files qualified as PFiles
import System.PosixCompat.Types
( DeviceID,
EpochTime,
Fd,
FileMode,
FileOffset,
GroupID,
Limit,
UserID,
)
data PosixCompatFiles :: Effect
type instance DispatchOf PosixCompatFiles = Static WithSideEffects
data instance StaticRep PosixCompatFiles = MkPosixFilesCompat
runPosixFilesCompat ::
(HasCallStack, IOE :> es) =>
Eff (PosixCompatFiles : es) a ->
Eff es a
runPosixFilesCompat :: forall (es :: [Effect]) a.
(HasCallStack, IOE :> es) =>
Eff (PosixCompatFiles : es) a -> Eff es a
runPosixFilesCompat = StaticRep PosixCompatFiles
-> Eff (PosixCompatFiles : es) a -> Eff es a
forall (e :: Effect) (sideEffects :: SideEffects) (es :: [Effect])
a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects,
MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es a
evalStaticRep StaticRep PosixCompatFiles
MkPosixFilesCompat
setFileMode ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
FileMode ->
Eff es ()
setFileMode :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> FileMode -> Eff es ()
setFileMode FilePath
p = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FileMode -> IO ()) -> FileMode -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FileMode -> IO ()
PFiles.setFileMode FilePath
p
setFdMode ::
( HasCallStack,
PosixCompatFiles :> es
) =>
Fd ->
FileMode ->
Eff es ()
setFdMode :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
Fd -> FileMode -> Eff es ()
setFdMode Fd
p = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FileMode -> IO ()) -> FileMode -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fd -> FileMode -> IO ()
PFiles.setFdMode Fd
p
setFileCreationMask ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FileMode ->
Eff es FileMode
setFileCreationMask :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FileMode -> Eff es FileMode
setFileCreationMask = IO FileMode -> Eff es FileMode
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO FileMode -> Eff es FileMode)
-> (FileMode -> IO FileMode) -> FileMode -> Eff es FileMode
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileMode -> IO FileMode
PFiles.setFileCreationMask
fileAccess ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Bool ->
Bool ->
Bool ->
Eff es Bool
fileAccess :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Bool -> Bool -> Bool -> Eff es Bool
fileAccess FilePath
p Bool
b Bool
c = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Bool -> IO Bool) -> Bool -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Bool -> Bool -> Bool -> IO Bool
PFiles.fileAccess FilePath
p Bool
b Bool
c
fileExist ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Eff es Bool
fileExist :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es Bool
fileExist = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (FilePath -> IO Bool) -> FilePath -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO Bool
PFiles.fileExist
getFileStatus ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Eff es FileStatus
getFileStatus :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es FileStatus
getFileStatus = IO FileStatus -> Eff es FileStatus
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO FileStatus -> Eff es FileStatus)
-> (FilePath -> IO FileStatus) -> FilePath -> Eff es FileStatus
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FileStatus
PFiles.getFileStatus
getFdStatus ::
( HasCallStack,
PosixCompatFiles :> es
) =>
Fd ->
Eff es FileStatus
getFdStatus :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
Fd -> Eff es FileStatus
getFdStatus = IO FileStatus -> Eff es FileStatus
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO FileStatus -> Eff es FileStatus)
-> (Fd -> IO FileStatus) -> Fd -> Eff es FileStatus
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fd -> IO FileStatus
PFiles.getFdStatus
getSymbolicLinkStatus ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Eff es FileStatus
getSymbolicLinkStatus :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es FileStatus
getSymbolicLinkStatus = IO FileStatus -> Eff es FileStatus
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO FileStatus -> Eff es FileStatus)
-> (FilePath -> IO FileStatus) -> FilePath -> Eff es FileStatus
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FileStatus
PFiles.getSymbolicLinkStatus
createNamedPipe ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
FileMode ->
Eff es ()
createNamedPipe :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> FileMode -> Eff es ()
createNamedPipe FilePath
p = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FileMode -> IO ()) -> FileMode -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FileMode -> IO ()
PFiles.createNamedPipe FilePath
p
createDevice ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
FileMode ->
DeviceID ->
Eff es ()
createDevice :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> FileMode -> DeviceID -> Eff es ()
createDevice FilePath
p FileMode
m = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (DeviceID -> IO ()) -> DeviceID -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FileMode -> DeviceID -> IO ()
PFiles.createDevice FilePath
p FileMode
m
createLink ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
FilePath ->
Eff es ()
createLink :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> FilePath -> Eff es ()
createLink FilePath
p = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FilePath -> IO ()) -> FilePath -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> IO ()
PFiles.createLink FilePath
p
removeLink ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Eff es ()
removeLink :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es ()
removeLink = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FilePath -> IO ()) -> FilePath -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO ()
PFiles.removeLink
createSymbolicLink ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
FilePath ->
Eff es ()
createSymbolicLink :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> FilePath -> Eff es ()
createSymbolicLink FilePath
p = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FilePath -> IO ()) -> FilePath -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> IO ()
PFiles.createSymbolicLink FilePath
p
readSymbolicLink ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Eff es FilePath
readSymbolicLink :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es FilePath
readSymbolicLink = IO FilePath -> Eff es FilePath
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO FilePath -> Eff es FilePath)
-> (FilePath -> IO FilePath) -> FilePath -> Eff es FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
PFiles.readSymbolicLink
rename ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
FilePath ->
Eff es ()
rename :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> FilePath -> Eff es ()
rename FilePath
p = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FilePath -> IO ()) -> FilePath -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> IO ()
PFiles.rename FilePath
p
setOwnerAndGroup ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
UserID ->
GroupID ->
Eff es ()
setOwnerAndGroup :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> UserID -> GroupID -> Eff es ()
setOwnerAndGroup FilePath
p UserID
uid = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (GroupID -> IO ()) -> GroupID -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> UserID -> GroupID -> IO ()
PFiles.setOwnerAndGroup FilePath
p UserID
uid
setFdOwnerAndGroup ::
( HasCallStack,
PosixCompatFiles :> es
) =>
Fd ->
UserID ->
GroupID ->
Eff es ()
setFdOwnerAndGroup :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
Fd -> UserID -> GroupID -> Eff es ()
setFdOwnerAndGroup Fd
fd UserID
uid = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (GroupID -> IO ()) -> GroupID -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fd -> UserID -> GroupID -> IO ()
PFiles.setFdOwnerAndGroup Fd
fd UserID
uid
setSymbolicLinkOwnerAndGroup ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
UserID ->
GroupID ->
Eff es ()
setSymbolicLinkOwnerAndGroup :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> UserID -> GroupID -> Eff es ()
setSymbolicLinkOwnerAndGroup FilePath
p UserID
uid = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (GroupID -> IO ()) -> GroupID -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> UserID -> GroupID -> IO ()
PFiles.setSymbolicLinkOwnerAndGroup FilePath
p UserID
uid
setFileTimes ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
EpochTime ->
EpochTime ->
Eff es ()
setFileTimes :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> EpochTime -> EpochTime -> Eff es ()
setFileTimes FilePath
p EpochTime
t = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (EpochTime -> IO ()) -> EpochTime -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> EpochTime -> EpochTime -> IO ()
PFiles.setFileTimes FilePath
p EpochTime
t
touchFile ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Eff es ()
touchFile :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es ()
touchFile = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FilePath -> IO ()) -> FilePath -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO ()
PFiles.touchFile
setFileSize ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
FileOffset ->
Eff es ()
setFileSize :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> FileOffset -> Eff es ()
setFileSize FilePath
p = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FileOffset -> IO ()) -> FileOffset -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FileOffset -> IO ()
PFiles.setFileSize FilePath
p
setFdSize ::
( HasCallStack,
PosixCompatFiles :> es
) =>
Fd ->
FileOffset ->
Eff es ()
setFdSize :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
Fd -> FileOffset -> Eff es ()
setFdSize Fd
fd = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (FileOffset -> IO ()) -> FileOffset -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fd -> FileOffset -> IO ()
PFiles.setFdSize Fd
fd
getPathVar ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
PathVar ->
Eff es Limit
getPathVar :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> PathVar -> Eff es Limit
getPathVar FilePath
p = IO Limit -> Eff es Limit
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Limit -> Eff es Limit)
-> (PathVar -> IO Limit) -> PathVar -> Eff es Limit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> PathVar -> IO Limit
PFiles.getPathVar FilePath
p
getFdPathVar ::
( HasCallStack,
PosixCompatFiles :> es
) =>
Fd ->
PathVar ->
Eff es Limit
getFdPathVar :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
Fd -> PathVar -> Eff es Limit
getFdPathVar Fd
fd = IO Limit -> Eff es Limit
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Limit -> Eff es Limit)
-> (PathVar -> IO Limit) -> PathVar -> Eff es Limit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fd -> PathVar -> IO Limit
PFiles.getFdPathVar Fd
fd
throwIfWrongPathType ::
( HasCallStack,
PosixCompatFiles :> es
) =>
String ->
PathType ->
FilePath ->
Eff es ()
throwIfWrongPathType :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> PathType -> FilePath -> Eff es ()
throwIfWrongPathType FilePath
location PathType
expected FilePath
path = do
actual <- FilePath -> Eff es PathType
forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es PathType
getPathType FilePath
path
let err =
[FilePath] -> FilePath
forall a. Monoid a => [a] -> a
mconcat
[ FilePath
"Expected path to have type ",
PathType -> FilePath
forall a. IsString a => PathType -> a
displayPathType PathType
expected,
FilePath
", but detected ",
PathType -> FilePath
forall a. IsString a => PathType -> a
displayPathType PathType
actual
]
unless (expected == actual) $
FS.IO.throwFilePathIOError
path
location
InappropriateType
err
isPathType ::
( HasCallStack,
PosixCompatFiles :> es
) =>
PathType ->
FilePath ->
Eff es Bool
isPathType :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
PathType -> FilePath -> Eff es Bool
isPathType PathType
expected = (PathType -> Bool) -> Eff es PathType -> Eff es Bool
forall a b. (a -> b) -> Eff es a -> Eff es b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PathType -> PathType -> Bool
forall a. Eq a => a -> a -> Bool
== PathType
expected) (Eff es PathType -> Eff es Bool)
-> (FilePath -> Eff es PathType) -> FilePath -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Eff es PathType
forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es PathType
getPathType
getPathType ::
( HasCallStack,
PosixCompatFiles :> es
) =>
FilePath ->
Eff es PathType
getPathType :: forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es PathType
getPathType FilePath
path = do
FilePath -> Eff es FileStatus
forall (es :: [Effect]).
(HasCallStack, PosixCompatFiles :> es) =>
FilePath -> Eff es FileStatus
getSymbolicLinkStatus FilePath
path Eff es FileStatus -> (FileStatus -> PathType) -> Eff es PathType
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \FileStatus
status ->
if
| FileStatus -> Bool
PFiles.isSymbolicLink FileStatus
status -> PathType
PathTypeSymbolicLink
| FileStatus -> Bool
PFiles.isDirectory FileStatus
status -> PathType
PathTypeDirectory
| FileStatus -> Bool
PFiles.isRegularFile FileStatus
status -> PathType
PathTypeFile
| Bool
otherwise -> PathType
PathTypeOther