| Copyright | © 2016 Julian Ospald |
|---|---|
| License | BSD3 |
| 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 ignored by some of the more high-level functions (like easyCopy).
For other functions (like copyFile), the behavior on these file types is
unreliable/unsafe. Check the documentation of those functions for details.
- 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 ()
- createSymlink :: Path Abs -> ByteString -> 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.
For directory contents, this has the same behavior as easyCopy
and thus will ignore any file type that is not RegularFile,
SymbolicLink or Directory.
Safety/reliability concerns:
- not atomic
- examines filetypes explicitly
- an explicit check
throwDestinationInSourceis 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:
NoSuchThingif source directory does not existPermissionDeniedif output directory is not writablePermissionDeniedif source directory can't be openedInvalidArgumentif source directory is wrong type (symlink)InvalidArgumentif source directory is wrong type (regular file)AlreadyExistsif destination already existsSameFileif source and destination are the same file (HPathIOException)DestinationInSourceif destination is contained in source (HPathIOException)
copyDirRecursiveOverwrite Source #
Like copyDirRecursive except it overwrites contents of directories
if any.
For directory contents, this has the same behavior as easyCopyOverwrite
and thus will ignore any file type that is not RegularFile,
SymbolicLink or Directory.
Throws:
NoSuchThingif source directory does not existPermissionDeniedif output directory is not writablePermissionDeniedif source directory can't be openedInvalidArgumentif source directory is wrong type (symlink)InvalidArgumentif source directory is wrong type (regular file)SameFileif source and destination are the same file (HPathIOException)DestinationInSourceif destination is contained in source (HPathIOException)
Recreate a symlink.
Throws:
InvalidArgumentif source file is wrong type (not a symlink)PermissionDeniedif output directory cannot be written toPermissionDeniedif source directory cannot be openedAlreadyExistsif destination file already existsSameFileif 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.
Note that this is still sort of a low-level function and doesn't
examine file types. For a more high-level version, use easyCopy
instead.
Safety/reliability concerns:
- when used on
CharacterDevice, reads the "contents" and copies them to a regular file, which might take indefinitely - when used on
BlockDevice, may either read the "contents" and copy them to a regular file (potentially hanging indefinitely) or may create a regular empty destination file - when used on
NamedPipe, will hang indefinitely
Throws:
NoSuchThingif source file does not existNoSuchThingif source file is a aSocketPermissionDeniedif output directory is not writablePermissionDeniedif source directory can't be openedInvalidArgumentif source file is wrong type (symlink or directory)AlreadyExistsif destination already existsSameFileif source and destination are the same file (HPathIOException)
Note: calls sendfile and possibly read/write as fallback
Like copyFile except it overwrites the destination if it already
exists.
Safety/reliability concerns:
- when used on
CharacterDevice, reads the "contents" and copies them to a regular file, which might take indefinitely - when used on
BlockDevice, may either read the "contents" and copy them to a regular file (potentially hanging indefinitely) or may create a regular empty destination file - when used on
NamedPipe, will hang indefinitely - not atomic, since it uses read/write
Throws:
NoSuchThingif source file does not existNoSuchThingif source file is aSocketPermissionDeniedif output directory is not writablePermissionDeniedif source directory can't be openedInvalidArgumentif source file is wrong type (symlink or directory)SameFileif 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 a regular file, directory or symbolic link. In case of a symbolic link it is just recreated, even if it points to a directory. Any other file type is ignored.
Safety/reliability concerns:
- examines filetypes explicitly
- calls
copyDirRecursivefor 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.
Safety/reliability concerns:
- examines filetypes explicitly
- calls
copyDirRecursivefor directories
File deletion
deleteFile :: Path Abs -> IO () Source #
Deletes the given file. Raises eISDIR
if run on a directory. Does not follow symbolic links.
Throws:
InappropriateTypefor wrong file type (directory)NoSuchThingif the file does not existPermissionDeniedif the directory cannot be read
deleteDir :: Path Abs -> IO () Source #
Deletes the given directory, which must be empty, never symlinks.
Throws:
InappropriateTypefor wrong file type (symlink to directory)InappropriateTypefor wrong file type (regular file)NoSuchThingif directory does not existUnsatisfiedConstraintsif directory is not emptyPermissionDeniedif 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.
On directory contents this behaves like easyDelete
and thus will ignore any file type that is not RegularFile,
SymbolicLink or Directory.
Safety/reliability concerns:
- not atomic
- examines filetypes explicitly
Throws:
InappropriateTypefor wrong file type (symlink to directory)InappropriateTypefor wrong file type (regular file)NoSuchThingif directory does not existPermissionDeniedif we can't open or write to parent directory
easyDelete :: Path Abs -> IO () Source #
Deletes a file, directory or symlink. In case of directory, performs recursive deletion. In case of a symlink, the symlink file is deleted. Any other file type is ignored.
Safety/reliability concerns:
- examines filetypes explicitly
- calls
deleteDirRecursivefor 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:
PermissionDeniedif output directory cannot be written toAlreadyExistsif destination file already exists
createDir :: Path Abs -> IO () Source #
Create an empty directory at the given directory with the given filename.
Throws:
PermissionDeniedif output directory cannot be written toAlreadyExistsif destination directory already exists
Arguments
| :: Path Abs | destination file |
| -> ByteString | path the symlink points to |
| -> IO () |
Create a symlink.
Throws:
PermissionDeniedif output directory cannot be written toAlreadyExistsif destination file already exists
Note: calls symlink
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:
NoSuchThingif source file does not existPermissionDeniedif output directory cannot be written toPermissionDeniedif source directory cannot be openedUnsupportedOperationif source and destination are on different devicesFileDoesExistif destination file already exists (HPathIOException)DirDoesExistif destination directory already exists (HPathIOException)SameFileif 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
- since this function calls
easyCopyandeasyDeleteas a fallback torenameFile, file types that are notRegularFile,SymbolicLinkorDirectorymay be ignored
Throws:
NoSuchThingif source file does not existPermissionDeniedif output directory cannot be written toPermissionDeniedif source directory cannot be openedFileDoesExistif destination file already exists (HPathIOException)DirDoesExistif destination directory already exists (HPathIOException)SameFileif 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.
Ignores any file type that is not RegularFile, SymbolicLink or
Directory.
Safety/reliability concerns:
- copy-delete fallback is inherently non-atomic
- checks for file types and destination file existence explicitly
Throws:
NoSuchThingif source file does not existPermissionDeniedif output directory cannot be written toPermissionDeniedif source directory cannot be openedSameFileif 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:
NoSuchThingif directory does not existInappropriateTypeif file type is wrong (file)InappropriateTypeif file type is wrong (symlink to file)InappropriateTypeif file type is wrong (symlink to dir)PermissionDeniedif 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:
NoSuchThingif the file does not existPermissionDeniedif any part of the path is not accessible