Copyright | © 2016 Julian Ospald |
---|---|
License | GPL-2 |
Maintainer | Julian Ospald <hasufell@posteo.de> |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
HPath.IO
Contents
Description
This module provides high-level IO related file operations like copy, delete, move and so on. It only operates on Path Abs which guarantees us well-typed paths which are absolute.
Some functions are just path-safe wrappers around
unix functions, others have stricter exception handling
and some implement functionality that doesn't have a unix
counterpart (like copyDirRecursive
).
Some of these operations are due to their nature not atomic, which means they may do multiple syscalls which form one context. Some of them also have to examine the filetypes explicitly before the syscalls, so a reasonable decision can be made. That means the result is undefined if another process changes that context while the non-atomic operation is still happening. However, where possible, as few syscalls as possible are used and the underlying exception handling is kept.
Note: BlockDevice
, CharacterDevice
, NamedPipe
and Socket
are not explicitly supported right now. Calling any of these
functions on such a file may throw an exception or just do
nothing.
- data FileType
- copyDirRecursive :: Path Abs -> Path Abs -> IO ()
- copyDirRecursiveOverwrite :: Path Abs -> Path Abs -> IO ()
- recreateSymlink :: Path Abs -> Path Abs -> IO ()
- copyFile :: Path Abs -> Path Abs -> IO ()
- copyFileOverwrite :: Path Abs -> Path Abs -> IO ()
- easyCopy :: Path Abs -> Path Abs -> IO ()
- easyCopyOverwrite :: Path Abs -> Path Abs -> IO ()
- deleteFile :: Path Abs -> IO ()
- deleteDir :: Path Abs -> IO ()
- deleteDirRecursive :: Path Abs -> IO ()
- easyDelete :: Path Abs -> IO ()
- openFile :: Path Abs -> IO ProcessID
- executeFile :: Path Abs -> [ByteString] -> IO ProcessID
- createRegularFile :: Path Abs -> IO ()
- createDir :: Path Abs -> IO ()
- renameFile :: Path Abs -> Path Abs -> IO ()
- moveFile :: Path Abs -> Path Abs -> IO ()
- moveFileOverwrite :: Path Abs -> Path Abs -> IO ()
- newFilePerms :: FileMode
- newDirPerms :: FileMode
- getDirsFiles :: Path Abs -> IO [Path Abs]
- getFileType :: Path Abs -> IO FileType
- canonicalizePath :: Path Abs -> IO (Path Abs)
Types
File copying
Copies a directory recursively to the given destination. Does not follow symbolic links.
Safety/reliability concerns:
- not atomic
- examines filetypes explicitly
- an explicit check
throwDestinationInSource
is carried out for the top directory for basic sanity, because otherwise we might end up with an infinite copy loop... however, this operation is not carried out recursively (because it's slow)
Throws:
NoSuchThing
if source directory does not existPermissionDenied
if output directory is not writablePermissionDenied
if source directory can't be openedInvalidArgument
if source directory is wrong type (symlink)InvalidArgument
if source directory is wrong type (regular file)SameFile
if source and destination are the same file (HPathIOException
)AlreadyExists
if destination already existsDestinationInSource
if destination is contained in source (HPathIOException
)
copyDirRecursiveOverwrite Source
Like copyDirRecursive
except it overwrites contents of directories
if any.
Throws:
NoSuchThing
if source directory does not existPermissionDenied
if output directory is not writablePermissionDenied
if source directory can't be openedInvalidArgument
if source directory is wrong type (symlink)InvalidArgument
if source directory is wrong type (regular file)SameFile
if source and destination are the same file (HPathIOException
)DestinationInSource
if destination is contained in source (HPathIOException
)
Recreate a symlink.
Throws:
InvalidArgument
if symlink file is wrong type (file)InvalidArgument
if symlink file is wrong type (directory)PermissionDenied
if output directory cannot be written toPermissionDenied
if source directory cannot be openedAlreadyExists
if destination file already existsSameFile
if source and destination are the same file (HPathIOException
)
Note: calls symlink
Copies the given regular file to the given destination.
Neither follows symbolic links, nor accepts them.
For "copying" symbolic links, use recreateSymlink
instead.
Throws:
NoSuchThing
if source file does not existPermissionDenied
if output directory is not writablePermissionDenied
if source directory can't be openedInvalidArgument
if source file is wrong type (symlink)InvalidArgument
if source file is wrong type (directory)SameFile
if source and destination are the same file (HPathIOException
)AlreadyExists
if destination already exists
Note: calls sendfile
and possibly read
/write
as fallback
Like copyFile
except it overwrites the destination if it already
exists.
This also works if source and destination are the same file.
Safety/reliability concerns:
- not atomic, since it uses read/write
Throws:
NoSuchThing
if source file does not existPermissionDenied
if output directory is not writablePermissionDenied
if source directory can't be openedInvalidArgument
if source file is wrong type (symlink)InvalidArgument
if source file is wrong type (directory)SameFile
if source and destination are the same file (HPathIOException
)
Note: calls sendfile
and possibly read
/write
as fallback
easyCopy :: Path Abs -> Path Abs -> IO () Source
Copies anything. In case of a symlink, it is just recreated, even if it points to a directory.
Safety/reliability concerns:
- examines filetypes explicitly
- calls
copyDirRecursive
for directories
easyCopyOverwrite :: Path Abs -> Path Abs -> IO () Source
Like easyCopy
except it overwrites the destination if it already exists.
For directories, this overwrites contents without pruning them, so the resulting
directory may have more files than have been copied.
File deletion
deleteFile :: Path Abs -> IO () Source
Deletes the given file, does not follow symlinks. Raises eISDIR
if run on a directory. Does not follow symbolic links.
Throws:
InappropriateType
for wrong file type (directory)NoSuchThing
if the file does not existPermissionDenied
if the directory cannot be read
deleteDir :: Path Abs -> IO () Source
Deletes the given directory, which must be empty, never symlinks.
Throws:
InappropriateType
for wrong file type (symlink to directory)InappropriateType
for wrong file type (regular file)NoSuchThing
if directory does not existUnsatisfiedConstraints
if directory is not emptyPermissionDenied
if we can't open or write to parent directory
Notes: calls rmdir
deleteDirRecursive :: Path Abs -> IO () Source
Deletes the given directory recursively. Does not follow symbolic
links. Tries deleteDir
first before attemtping a recursive
deletion.
Safety/reliability concerns:
- not atomic
- examines filetypes explicitly
Throws:
InappropriateType
for wrong file type (symlink to directory)InappropriateType
for wrong file type (regular file)NoSuchThing
if directory does not existPermissionDenied
if we can't open or write to parent directory
easyDelete :: Path Abs -> IO () Source
Deletes a file, directory or symlink, whatever it may be. In case of directory, performs recursive deletion. In case of a symlink, the symlink file is deleted.
Safety/reliability concerns:
- examines filetypes explicitly
- calls
deleteDirRecursive
for directories
File opening
openFile :: Path Abs -> IO ProcessID Source
Opens a file appropriately by invoking xdg-open. The file type is not checked. This forks a process.
Arguments
:: Path Abs | program |
-> [ByteString] | arguments |
-> IO ProcessID |
Executes a program with the given arguments. This forks a process.
File creation
createRegularFile :: Path Abs -> IO () Source
Create an empty regular file at the given directory with the given filename.
Throws:
PermissionDenied
if output directory cannot be written toAlreadyExists
if destination file already exists
createDir :: Path Abs -> IO () Source
Create an empty directory at the given directory with the given filename.
Throws:
PermissionDenied
if output directory cannot be written toAlreadyExists
if destination directory already exists
File renaming/moving
renameFile :: Path Abs -> Path Abs -> IO () Source
Rename a given file with the provided filename. Destination and source
must be on the same device, otherwise eXDEV
will be raised.
Does not follow symbolic links, but renames the symbolic link file.
Safety/reliability concerns:
- has a separate set of exception handling, apart from the syscall
Throws:
NoSuchThing
if source file does not existPermissionDenied
if output directory cannot be written toPermissionDenied
if source directory cannot be openedUnsupportedOperation
if source and destination are on different devicesFileDoesExist
if destination file already existsDirDoesExist
if destination directory already existsSameFile
if destination and source are the same file (HPathIOException
)
Note: calls rename
(but does not allow to rename over existing files)
Move a file. This also works across devices by copy-delete fallback. And also works on directories.
Does not follow symbolic links, but renames the symbolic link file.
Safety/reliability concerns:
- copy-delete fallback is inherently non-atomic
Throws:
NoSuchThing
if source file does not existPermissionDenied
if output directory cannot be written toPermissionDenied
if source directory cannot be openedFileDoesExist
if destination file already existsDirDoesExist
if destination directory already existsSameFile
if destination and source are the same file (HPathIOException
)
Note: calls rename
(but does not allow to rename over existing files)
Like moveFile
, but overwrites the destination if it exists.
Does not follow symbolic links, but renames the symbolic link file.
Safety/reliability concerns:
- copy-delete fallback is inherently non-atomic
- checks for file types and destination file existence explicitly
Throws:
NoSuchThing
if source file does not existPermissionDenied
if output directory cannot be written toPermissionDenied
if source directory cannot be openedSameFile
if destination and source are the same file (HPathIOException
)
Note: calls rename
(but does not allow to rename over existing files)
File permissions
newFilePerms :: FileMode Source
Default permissions for a new file.
newDirPerms :: FileMode Source
Default permissions for a new directory.
Directory reading
Gets all filenames of the given directory. This excludes "." and "..". This version does not follow symbolic links.
Throws:
NoSuchThing
if directory does not existInappropriateType
if file type is wrong (file)InappropriateType
if file type is wrong (symlink to file)InappropriateType
if file type is wrong (symlink to dir)PermissionDenied
if directory cannot be opened
Filetype operations
getFileType :: Path Abs -> IO FileType Source
Get the file type of the file located at the given path. Does not follow symbolic links.
Throws:
NoSuchThing
if the file does not existPermissionDenied
if any part of the path is not accessible