-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Abstract interface for the file system -- -- Abstract interface for the file system. @package fs-api @version 0.3.0.0 -- | CallStack with a nicer Show instance -- -- Use of this module is intended to replace import of -- GHC.Stack module System.FS.CallStack prettyCallStack :: HasCallStack => PrettyCallStack -- | CallStack with Show instance using prettyCallStack data PrettyCallStack -- | Request a CallStack. -- -- NOTE: The implicit parameter ?callStack :: CallStack is an -- implementation detail and should not be considered part of the -- CallStack API, we may decide to change the implementation in -- the future. type HasCallStack = ?callStack :: CallStack instance GHC.Show.Show System.FS.CallStack.PrettyCallStack -- | Condensed but human-readable output (like Show). module System.FS.Condense -- | Condensed but human-readable output class Condense a condense :: Condense a => a -> String class Condense1 f liftCondense :: Condense1 f => (a -> String) -> f a -> String -- | Lift the standard condense function through the type -- constructor condense1 :: (Condense1 f, Condense a) => f a -> String instance GHC.Show.Show a => GHC.Show.Show (System.FS.Condense.CondenseAsShow a) instance System.FS.Condense.Condense GHC.Types.Bool instance System.FS.Condense.Condense GHC.Types.Int instance System.FS.Condense.Condense GHC.Int.Int64 instance System.FS.Condense.Condense GHC.Types.Word instance System.FS.Condense.Condense GHC.Word.Word32 instance System.FS.Condense.Condense GHC.Word.Word64 instance System.FS.Condense.Condense GHC.Num.Natural.Natural instance GHC.Show.Show a => System.FS.Condense.Condense (System.FS.Condense.CondenseAsShow a) instance System.FS.Condense.Condense1 [] instance System.FS.Condense.Condense1 Data.Set.Internal.Set instance System.FS.Condense.Condense GHC.Base.Void instance System.FS.Condense.Condense Data.Text.Internal.Text instance System.FS.Condense.Condense GHC.Real.Rational instance System.FS.Condense.Condense a => System.FS.Condense.Condense [a] instance System.FS.Condense.Condense a => System.FS.Condense.Condense (GHC.Maybe.Maybe a) instance System.FS.Condense.Condense a => System.FS.Condense.Condense (Data.Set.Internal.Set a) instance (System.FS.Condense.Condense a, System.FS.Condense.Condense b) => System.FS.Condense.Condense (a, b) instance (System.FS.Condense.Condense a, System.FS.Condense.Condense b, System.FS.Condense.Condense c) => System.FS.Condense.Condense (a, b, c) instance (System.FS.Condense.Condense a, System.FS.Condense.Condense b, System.FS.Condense.Condense c, System.FS.Condense.Condense d) => System.FS.Condense.Condense (a, b, c, d) instance (System.FS.Condense.Condense a, System.FS.Condense.Condense b, System.FS.Condense.Condense c, System.FS.Condense.Condense d, System.FS.Condense.Condense e) => System.FS.Condense.Condense (a, b, c, d, e) instance (System.FS.Condense.Condense k, System.FS.Condense.Condense a) => System.FS.Condense.Condense (Data.Map.Internal.Map k a) instance System.FS.Condense.Condense Data.ByteString.Internal.Type.ByteString instance System.FS.Condense.Condense Data.ByteString.Lazy.Internal.ByteString module System.FS.API.Types -- | When opening a file: data AllowExisting -- | The file may already exist. If it does, it is reopened. If it doesn't, -- it is created. AllowExisting :: AllowExisting -- | The file may not yet exist. If it does, an error -- (FsResourceAlreadyExist) is thrown. MustBeNew :: AllowExisting -- | How to hOpen a new file. data OpenMode ReadMode :: OpenMode WriteMode :: AllowExisting -> OpenMode AppendMode :: AllowExisting -> OpenMode ReadWriteMode :: AllowExisting -> OpenMode -- | A mode that determines the effect of hSeek hdl mode i. data () => SeekMode -- | the position of hdl is set to i. AbsoluteSeek :: SeekMode -- | the position of hdl is set to offset i from the -- current position. RelativeSeek :: SeekMode -- | the position of hdl is set to offset i from the end -- of the file. SeekFromEnd :: SeekMode allowExisting :: OpenMode -> AllowExisting -- | Mount point -- -- FsPaths are not absolute paths, but must be interpreted with -- respect to a particualar mount point. newtype MountPoint MountPoint :: FilePath -> MountPoint fsFromFilePath :: MountPoint -> FilePath -> Maybe FsPath -- | Create a path from a list of directory/file names. All of the names -- should be non-empty. fsPathFromList :: [Text] -> FsPath -- | Drop the final component of the path -- -- Undefined if the path is empty. fsPathInit :: HasCallStack => FsPath -> FsPath -- | Split FsPath is essentially (init fp, last fp) -- -- Like init and last, Nothing if empty. fsPathSplit :: FsPath -> Maybe (FsPath, Text) fsPathToList :: FsPath -> [Text] fsToFilePath :: MountPoint -> FsPath -> FilePath -- | Constructor for FsPath ensures path is in normal form mkFsPath :: [String] -> FsPath -- | Add an extension, even if there is already one there. -- -- This works similarly to <.>. (<.>) :: FsPath -> String -> FsPath infixr 7 <.> -- | An alias for <.>. addExtension :: FsPath -> String -> FsPath -- | Combine two paths with a path separator. -- -- This works similarly to </>, but since the arguments are -- relative paths, the corner cases for </> do not apply. -- Specifically, the second path will never start with a path separator -- or a drive letter, so the result is simply the concatenation of the -- two paths. -- -- If either operand is empty, the other operand is returned. The result -- of combining two empty paths is the empty path () :: FsPath -> FsPath -> FsPath infixr 5 -- | An alias for </>. combine :: FsPath -> FsPath -> FsPath -- | A relative path. -- --

Invariant

-- -- The user of this library is tasked with picking sensible names of -- directories/files on a path. Amongst others, the following should -- hold: -- -- -- -- In particular, names that satisfy these invariants should result in an -- FsPath that remains relative to the HasFS instance root. For -- example, an FsPath ["/"] would try to access the root -- folder, which is most likely outside of the scope of the HasFS -- instance. -- -- ".." should not be used because fs-sim will not be -- able to follow these types of back-links. fs-sim will -- interpret ".." as a directory name instead. data FsPath data Handle h Handle :: !h -> !FsPath -> Handle h -- | The raw underlying handle [handleRaw] :: Handle h -> !h -- | The path corresponding to this handle -- -- This is primarily useful for error reporting. [handlePath] :: Handle h -> !FsPath newtype AbsOffset AbsOffset :: Word64 -> AbsOffset [unAbsOffset] :: AbsOffset -> Word64 data FsError FsError :: FsErrorType -> FsErrorPath -> String -> Maybe Errno -> PrettyCallStack -> Bool -> FsError -- | Error type [fsErrorType] :: FsError -> FsErrorType -- | Path to the file [fsErrorPath] :: FsError -> FsErrorPath -- | Human-readable string giving additional information about the error [fsErrorString] :: FsError -> String -- | The Errno, if available. This is more precise than the -- FsErrorType. [fsErrorNo] :: FsError -> Maybe Errno -- | Call stack [fsErrorStack] :: FsError -> PrettyCallStack -- | Is this error due to a limitation of the mock file system? -- -- The mock file system does not all of Posix's features and quirks. This -- flag will be set for such unsupported IO calls. Real I/O calls would -- not have thrown an error for these calls. [fsLimitation] :: FsError -> Bool -- | For better error reporting to the end user, we want to include the -- mount point of the file. But the mountpoint may not always be -- available, like when we mock the fs or we simulate fs errors. data FsErrorPath FsErrorPath :: Maybe MountPoint -> FsPath -> FsErrorPath data FsErrorType FsIllegalOperation :: FsErrorType -- | e.g the user tried to open a directory with hOpen rather than a file. FsResourceInappropriateType :: FsErrorType FsResourceAlreadyInUse :: FsErrorType FsResourceDoesNotExist :: FsErrorType FsResourceAlreadyExist :: FsErrorType FsReachedEOF :: FsErrorType FsDeviceFull :: FsErrorType FsTooManyOpenFiles :: FsErrorType FsInsufficientPermissions :: FsErrorType FsInvalidArgument :: FsErrorType -- | Used for all other error types FsOther :: FsErrorType fsToFsErrorPath :: MountPoint -> FsPath -> FsErrorPath -- | Like fsToFsErrorPath, but when we don't have a -- MountPoint fsToFsErrorPathUnmounted :: FsPath -> FsErrorPath hasMountPoint :: FsError -> Bool isFsErrorType :: FsErrorType -> FsError -> Bool prettyFsError :: FsError -> String -- | Check if two errors are semantically the same error -- -- This ignores the error string, the errno, and the callstack. sameFsError :: FsError -> FsError -> Bool -- | Translate exceptions thrown by IO functions to FsError -- -- We take the FsPath as an argument. We could try to translate -- back from a FilePath to an FsPath (given a -- MountPoint), but we know the FsPath at all times anyway -- and not all IO exceptions actually include a filepath. ioToFsError :: HasCallStack => FsErrorPath -> IOError -> FsError -- | Assign an FsErrorType to the given IOError. -- -- Note that we don't always use the classification made by -- errnoToIOError (also see Error) because it combines some -- errors into one IOErrorType, e.g., EMFILE (too many -- open files) and ENOSPC (no space left on device) both result -- in ResourceExhausted while we want to keep them separate. For -- this reason, we do a classification of our own based on the -- errno while sometimes deferring to the existing -- classification. -- -- See the ERRNO(3) man page for the meaning of the different errnos. ioToFsErrorType :: IOError -> FsErrorType instance GHC.Show.Show System.FS.API.Types.AllowExisting instance GHC.Classes.Eq System.FS.API.Types.AllowExisting instance GHC.Show.Show System.FS.API.Types.OpenMode instance GHC.Classes.Eq System.FS.API.Types.OpenMode instance Control.DeepSeq.NFData System.FS.API.Types.FsPath instance GHC.Generics.Generic System.FS.API.Types.FsPath instance GHC.Classes.Ord System.FS.API.Types.FsPath instance GHC.Classes.Eq System.FS.API.Types.FsPath instance GHC.Generics.Generic (System.FS.API.Types.Handle h) instance GHC.Show.Show System.FS.API.Types.AbsOffset instance GHC.Num.Num System.FS.API.Types.AbsOffset instance GHC.Enum.Bounded System.FS.API.Types.AbsOffset instance GHC.Enum.Enum System.FS.API.Types.AbsOffset instance GHC.Classes.Ord System.FS.API.Types.AbsOffset instance GHC.Classes.Eq System.FS.API.Types.AbsOffset instance GHC.Classes.Eq System.FS.API.Types.FsErrorType instance GHC.Show.Show System.FS.API.Types.FsErrorType instance GHC.Show.Show System.FS.API.Types.FsError instance GHC.Exception.Type.Exception System.FS.API.Types.FsError instance Control.DeepSeq.NFData h => Control.DeepSeq.NFData (System.FS.API.Types.Handle h) instance GHC.Classes.Eq h => GHC.Classes.Eq (System.FS.API.Types.Handle h) instance GHC.Show.Show (System.FS.API.Types.Handle h) instance System.FS.Condense.Condense (System.FS.API.Types.Handle h) instance GHC.Show.Show System.FS.API.Types.FsErrorPath instance System.FS.Condense.Condense System.FS.API.Types.FsErrorPath instance GHC.Classes.Eq System.FS.API.Types.FsErrorPath instance GHC.Show.Show System.FS.API.Types.FsPath instance System.FS.Condense.Condense System.FS.API.Types.FsPath instance System.FS.Condense.Condense System.FS.API.Types.OpenMode instance System.FS.Condense.Condense System.FS.API.Types.AllowExisting instance System.FS.Condense.Condense GHC.IO.Device.SeekMode -- | An abstract view over the filesystem. module System.FS.API -- | Abstract interface for performing file I/O -- -- data HasFS m h HasFS :: m String -> (HasCallStack => FsPath -> OpenMode -> m (Handle h)) -> (HasCallStack => Handle h -> m ()) -> (HasCallStack => Handle h -> m Bool) -> (HasCallStack => Handle h -> SeekMode -> Int64 -> m ()) -> (HasCallStack => Handle h -> Word64 -> m ByteString) -> (HasCallStack => Handle h -> Word64 -> AbsOffset -> m ByteString) -> (HasCallStack => Handle h -> ByteString -> m Word64) -> (HasCallStack => Handle h -> Word64 -> m ()) -> (HasCallStack => Handle h -> m Word64) -> (HasCallStack => FsPath -> m ()) -> (HasCallStack => Bool -> FsPath -> m ()) -> (HasCallStack => FsPath -> m (Set String)) -> (HasCallStack => FsPath -> m Bool) -> (HasCallStack => FsPath -> m Bool) -> (HasCallStack => FsPath -> m ()) -> (HasCallStack => FsPath -> m ()) -> (HasCallStack => FsPath -> FsPath -> m ()) -> (FsPath -> FsErrorPath) -> (FsPath -> m FilePath) -> (HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> m ByteCount) -> (HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> AbsOffset -> m ByteCount) -> (HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> m ByteCount) -> (HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> AbsOffset -> m ByteCount) -> HasFS m h -- | Debugging: human-readable description of file system state [dumpState] :: HasFS m h -> m String -- | Open a file [hOpen] :: HasFS m h -> HasCallStack => FsPath -> OpenMode -> m (Handle h) -- | Close a file [hClose] :: HasFS m h -> HasCallStack => Handle h -> m () -- | Is the handle open? [hIsOpen] :: HasFS m h -> HasCallStack => Handle h -> m Bool -- | Seek handle -- -- The offset is an Int64 rather than a Word64 because it -- may be negative (for use in relative positioning). -- -- Unlike the Posix lseek, hSeek does not return the new -- seek position because the value returned by Posix is rather strange -- and unreliable and we don't want to emulate it's behaviour. [hSeek] :: HasFS m h -> HasCallStack => Handle h -> SeekMode -> Int64 -> m () -- | Try to read n bytes from a handle -- -- When at the end of the file, an empty bytestring will be returned. -- -- The returned bytestring will typically have length n, but may -- be shorter in case of a partial read, see #277. However, a partial -- read will always return at least 1 byte, as returning 0 bytes would -- mean that we have reached EOF. -- -- Postcondition: for the length of the returned bytestring bs -- we have length bs >= 0 and length bs <= n. [hGetSome] :: HasFS m h -> HasCallStack => Handle h -> Word64 -> m ByteString -- | Same as hGetSome, but does not affect the file offset. An -- additional argument is used to specify the offset. This allows it to -- be called concurrently for the same file handle. However, the actual -- level of parallelism achieved depends on the implementation and the -- operating system: generally on Unix it will be "more parallel" than on -- Windows. [hGetSomeAt] :: HasFS m h -> HasCallStack => Handle h -> Word64 -> AbsOffset -> m ByteString -- | Write to a handle -- -- The return value indicates the number of bytes written and will -- typically be equal to l, the length of the bytestring, but -- may be shorter in case of a partial write, see #277. -- -- If nothing can be written at all, an exception will be thrown. -- -- Postcondition: the return value n is n > 0 and -- n <= l, unless the given bytestring is empty, in which -- case n can be 0. [hPutSome] :: HasFS m h -> HasCallStack => Handle h -> ByteString -> m Word64 -- | Truncate the file to the specified size -- -- NOTE: Only supported in append mode. [hTruncate] :: HasFS m h -> HasCallStack => Handle h -> Word64 -> m () -- | Return current file size -- -- NOTE: This is not thread safe (changes made to the file in other -- threads may affect this thread). [hGetSize] :: HasFS m h -> HasCallStack => Handle h -> m Word64 -- | Create new directory [createDirectory] :: HasFS m h -> HasCallStack => FsPath -> m () -- | Create new directory if it doesn't exist. -- -- createDirectoryIfMissing True will also try to create all -- parent dirs. [createDirectoryIfMissing] :: HasFS m h -> HasCallStack => Bool -> FsPath -> m () -- | List contents of a directory [listDirectory] :: HasFS m h -> HasCallStack => FsPath -> m (Set String) -- | Check if the path exists and is a directory [doesDirectoryExist] :: HasFS m h -> HasCallStack => FsPath -> m Bool -- | Check if the path exists and is a file [doesFileExist] :: HasFS m h -> HasCallStack => FsPath -> m Bool -- | Remove the directory (which must exist) and its contents [removeDirectoryRecursive] :: HasFS m h -> HasCallStack => FsPath -> m () -- | Remove the file (which must exist) [removeFile] :: HasFS m h -> HasCallStack => FsPath -> m () -- | Rename the file (which must exist) from the first path to the second -- path. If there is already a file at the latter path, it is replaced by -- the new one. -- -- NOTE: only works for files within the same folder. [renameFile] :: HasFS m h -> HasCallStack => FsPath -> FsPath -> m () -- | Useful for better error reporting [mkFsErrorPath] :: HasFS m h -> FsPath -> FsErrorPath -- | Create an absolute FilePath from a relative FsPath. -- -- This is an escape hatch for creating absolute paths when m -- ~IO. -- -- Postcondition: Should throw an error for any m that is not -- IO (or for which we do not have MonadIO m). [unsafeToFilePath] :: HasFS m h -> FsPath -> m FilePath -- | Like hGetSome, but the bytes are read into a user-supplied -- buffer. See User-supplied buffers. [hGetBufSome] :: HasFS m h -> HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> m ByteCount -- | Like hGetSomeAt, but the bytes are read into a user-supplied -- buffer. See User-supplied buffers. [hGetBufSomeAt] :: HasFS m h -> HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> AbsOffset -> m ByteCount -- | Like hPutSome, but the bytes are written from a user-supplied -- buffer. See User-supplied buffers. [hPutBufSome] :: HasFS m h -> HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> m ByteCount -- | Like hPutSome, but the bytes are written from a user-supplied -- buffer at a given file offset. This offset does not affect the offset -- stored in the file handle (see also hGetSomeAt). See -- User-supplied buffers. [hPutBufSomeAt] :: HasFS m h -> HasCallStack => Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> AbsOffset -> m ByteCount -- | Returns True when the handle was still open. hClose' :: (HasCallStack, Monad m) => HasFS m h -> Handle h -> m Bool withFile :: (HasCallStack, MonadThrow m) => HasFS m h -> FsPath -> OpenMode -> (Handle h -> m a) -> m a -- | It is often inconvenient to have to parameterise over h. This -- data type hides an existential h parameter of a HasFS. data SomeHasFS m [SomeHasFS] :: Eq h => HasFS m h -> SomeHasFS m -- | Absolute offset into a buffer (i.e., MutableByteArray). -- -- Can be negative, because buffer offsets can be added together to -- change offset positions. This is similar to plusPtr for -- Ptr types. However, note that reading or writing from a -- buffer at a negative offset leads to undefined behaviour. newtype BufferOffset BufferOffset :: Int -> BufferOffset [unBufferOffset] :: BufferOffset -> Int -- | Wrapper for hGetBufSome that ensures that we read exactly as -- many bytes as requested. If EOF is found before the requested number -- of bytes is read, an FsError exception is thrown. hGetBufExactly :: forall m h. (HasCallStack, MonadThrow m) => HasFS m h -> Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> m ByteCount -- | Wrapper for hGetBufSomeAt that ensures that we read exactly as -- many bytes as requested. If EOF is found before the requested number -- of bytes is read, an FsError exception is thrown. hGetBufExactlyAt :: forall m h. (HasCallStack, MonadThrow m) => HasFS m h -> Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> AbsOffset -> m ByteCount -- | Wrapper for hPutBufSome that ensures we write exactly as many -- bytes as requested. hPutBufExactly :: forall m h. (HasCallStack, MonadThrow m) => HasFS m h -> Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> m ByteCount -- | Wrapper for hPutBufSomeAt that ensures we write exactly as many -- bytes as requested. hPutBufExactlyAt :: forall m h. (HasCallStack, MonadThrow m) => HasFS m h -> Handle h -> MutableByteArray (PrimState m) -> BufferOffset -> ByteCount -> AbsOffset -> m ByteCount instance Control.DeepSeq.NFData (System.FS.API.HasFS m h) instance GHC.Show.Show System.FS.API.BufferOffset instance GHC.Num.Num System.FS.API.BufferOffset instance GHC.Enum.Bounded System.FS.API.BufferOffset instance GHC.Enum.Enum System.FS.API.BufferOffset instance GHC.Classes.Ord System.FS.API.BufferOffset instance GHC.Classes.Eq System.FS.API.BufferOffset module System.FS.API.Strict -- | This function makes sure that the whole ByteString is written. hPutAllStrict :: forall m h. (HasCallStack, Monad m) => HasFS m h -> Handle h -> ByteString -> m Word64 module System.FS.API.Lazy -- | Read all the data from the given file handle 64kB at a time. -- -- Stops when EOF is reached. hGetAll :: Monad m => HasFS m h -> Handle h -> m ByteString -- | Like hGetAll, but is thread safe since it does not change or -- depend on the file offset. pread syscall is used internally. hGetAllAt :: Monad m => HasFS m h -> Handle h -> AbsOffset -> m ByteString -- | Makes sure it reads all requested bytes. If eof is found before all -- bytes are read, it throws an exception. hGetExactly :: forall m h. (HasCallStack, MonadThrow m) => HasFS m h -> Handle h -> Word64 -> m ByteString -- | Like hGetExactly, but is thread safe since it does not change -- or depend on the file offset. pread syscall is used -- internally. hGetExactlyAt :: forall m h. (HasCallStack, MonadThrow m) => HasFS m h -> Handle h -> Word64 -> AbsOffset -> m ByteString -- | This function makes sure that the whole Builder is written. -- -- The chunk size of the resulting ByteString determines how much -- memory will be used while writing to the handle. hPut :: forall m h. (HasCallStack, Monad m) => HasFS m h -> Handle h -> Builder -> m Word64 -- | This function makes sure that the whole ByteString is written. hPutAll :: forall m h. (HasCallStack, Monad m) => HasFS m h -> Handle h -> ByteString -> m Word64 -- | Support for CRC module System.FS.CRC newtype CRC CRC :: Word32 -> CRC [getCRC] :: CRC -> Word32 computeCRC :: forall a. CRC32 a => a -> CRC initCRC :: CRC updateCRC :: forall a. CRC32 a => a -> CRC -> CRC -- | Variation on hGetAllAt that also computes a CRC hGetAllAtCRC :: forall m h. Monad m => HasFS m h -> Handle h -> AbsOffset -> m (ByteString, CRC) -- | Variation on hGetExactlyAt that also computes a CRC hGetExactlyAtCRC :: forall m h. (HasCallStack, MonadThrow m) => HasFS m h -> Handle h -> Word64 -> AbsOffset -> m (ByteString, CRC) -- | Variation on hPutAll that also computes a CRC hPutAllCRC :: forall m h. (HasCallStack, Monad m) => HasFS m h -> Handle h -> ByteString -> m (Word64, CRC) instance Foreign.Storable.Storable System.FS.CRC.CRC instance GHC.Generics.Generic System.FS.CRC.CRC instance GHC.Show.Show System.FS.CRC.CRC instance GHC.Classes.Eq System.FS.CRC.CRC -- | This module is mainly meant to be used for the IO -- implementation of HasFS. module System.FS.IO.Handle -- | File handlers for the IO instance for HasFS. This is parametric on the -- os. -- -- The FilePath is used to improve error messages. The MVar -- is used to implement close. osHandle is Fd for unix and -- HANDLE for Windows. data HandleOS osHandle HandleOS :: FilePath -> MVar (Maybe osHandle) -> HandleOS osHandle [filePath] :: HandleOS osHandle -> FilePath [handle] :: HandleOS osHandle -> MVar (Maybe osHandle) -- | This is a no-op when the handle is already closed. closeHandleOS :: HandleOS osHandle -> (osHandle -> IO ()) -> IO () isHandleClosedException :: IOException -> Bool isOpenHandleOS :: HandleOS osHandle -> IO Bool -- | This is meant to be used for the implementation of individual file -- system commands. Using it for larger scopes woud not be correct, since -- we would not notice if the handle is closed. withOpenHandle :: String -> HandleOS osHandle -> (osHandle -> IO a) -> IO a instance GHC.Classes.Eq (System.FS.IO.Handle.HandleOS a) instance GHC.Show.Show (System.FS.IO.Handle.HandleOS a) -- | This module is mainly meant to be used for the IO -- implementation of HasFS. module System.FS.IO.Unix type FHandle = HandleOS Fd -- | Close handle -- -- This is a no-op when the handle is already closed. close :: FHandle -> IO () -- | File size of the given file pointer -- -- NOTE: This is not thread safe (changes made to the file in other -- threads may affect this thread). getSize :: FHandle -> IO Word64 -- | Opens a file from disk. open :: FilePath -> OpenMode -> IO Fd pread :: FHandle -> Word64 -> Word64 -> IO ByteString -- | preadBuf fh buf c off reads c bytes into the -- buffer buf from the file handle fh at the file -- offset off. This does not move the position of the file -- handle. preadBuf :: FHandle -> Ptr Word8 -> ByteCount -> FileOffset -> IO ByteCount -- | pwriteBuf fh buf c off writes c bytes from -- the data in the buffer buf to the file handle fh at -- the file offset off. This does not move the position of the -- file handle. pwriteBuf :: FHandle -> Ptr Word8 -> ByteCount -> FileOffset -> IO ByteCount -- | Reads a given number of bytes from the input FHandle. read :: FHandle -> Word64 -> IO ByteString readBuf :: FHandle -> Ptr Word8 -> ByteCount -> IO ByteCount -- | Seek within the file. -- -- The offset may be negative. -- -- We don't return the new offset since the behaviour of lseek is rather -- odd (e.g., the file pointer may not actually be moved until a -- subsequent write) seek :: FHandle -> SeekMode -> Int64 -> IO () -- | Truncates the file managed by the input FHandle to the input -- size. truncate :: FHandle -> Word64 -> IO () -- | Writes the data pointed by the input 'Ptr Word8' into the input -- FHandle. write :: FHandle -> Ptr Word8 -> Int64 -> IO Word32 writeBuf :: FHandle -> Ptr Word8 -> ByteCount -> IO ByteCount -- | IO implementation of the HasFS interface. module System.FS.IO -- | File handlers for the IO instance for HasFS -- -- We store the path the handle points to for better error messages type HandleIO = FHandle -- | IO implementation of the HasFS interface using the -- real file system. -- -- The concrete implementation depends on the OS distribution, but -- behaviour should be similar across distributions. ioHasFS :: (MonadIO m, PrimState IO ~ PrimState m) => MountPoint -> HasFS m HandleIO