Struct fs_at::OpenOptions
source · #[non_exhaustive]pub struct OpenOptions { /* private fields */ }Expand description
Similar to std::fs::OpenOptions, this struct is used to parameterise the
various at functions, which are then called on the struct itself. Typical
use is to create a struct via Default::default or
OpenOptions::default(), and then customise it as desired (e.g. setting
security descriptors on windows, or mode on unix) using an appropriate
platform specific trait, finishing up with the desired manipulation e.g.
mkdirat.
A note on the manipulations: they take a directory handle as &File. This is believed safe but if you have reason to disagree please file a bug.
- Rust’s borrow checker ensures that File::drop() will not be called concurrently with a manipulation, thus the file will still be open (in the absence of unsafe Rust or non-Rust libraries)
- the openat family of functions do not document any state changes to the
base fd that names are resolved against. Only
read_diris documented as changing state. - similarly on Windows, NtCreateFile is not documented as changing any state when creating a file relative to the handle.
Implementations§
source§impl OpenOptions
impl OpenOptions
sourcepub fn read(&mut self, read: bool) -> &mut Self
pub fn read(&mut self, read: bool) -> &mut Self
Sets the option for read access.
This option, when true, will indicate that the file should be read-able if opened.
use fs_at::OpenOptions;
let file = OpenOptions::default().read(true).open_at(&mut parent, "foo");
sourcepub fn write(&mut self, write: OpenOptionsWriteMode) -> &mut Self
pub fn write(&mut self, write: OpenOptionsWriteMode) -> &mut Self
Sets the option for write access.
See OpenOptionsWriteMode for the details of each mode.
This option on its own is not enough to create a new file.
use fs_at::OpenOptions;
let file = OpenOptions::default().write(OpenOptionsWriteMode::Write).open_at(&mut parent, "foo.txt");
sourcepub fn truncate(&mut self, truncate: bool) -> &mut Self
pub fn truncate(&mut self, truncate: bool) -> &mut Self
Sets the option for truncating a previous file.
If a file is successfully opened with this option set it will truncate the file to 0 length if it already exists.
The file must be opened with write access for truncate to work.
Behaviour of truncate on directories and symlink files is unspecified.
On Windows a file-symlink from A to B when truncated with no-follow
(.write(true).truncate(true).follow(false) ) will convert the target from
a symlink to an empty file. The Windows behaviour is compatible with the definition of O_TRUNC
on Unix - this case is unspecified. This cannot be made race-free, however
it seems like a race will at most destroy a link, not permit elevation of
privileges, so this can be handled by the caller by doing a readlink first,
treating a success as an EEXISTS error, and then actually performing the
no-follow truncation.
On Unix platforms EEXISTS tends to be returned instead.
use std::fs::OpenOptions;
let file = OpenOptions::new().write(OpenOptionsWriteMode::Append).truncate(true).open_at(&mut parent, "foo.txt");
sourcepub fn create(&mut self, create: bool) -> &mut Self
pub fn create(&mut self, create: bool) -> &mut Self
Set the option to create a new file when missing, while still opening
existing files. Unlike the Rust stdlib, an options with write set to
OpenOptionsWriteMode::None can still be used to create a new file.
Platform specific:
- on Windows, safely opens existing directories or makes new ones.
- on Linux, consumes EEXIST when making a directory and returns an existing directory at that path if it exists.
sourcepub fn create_new(&mut self, create_new: bool) -> &mut Self
pub fn create_new(&mut self, create_new: bool) -> &mut Self
Set the option to create a new file, rejecting existing entries at the pathname, whether links or directories.
This is requested from the OS as an atomic operation, to provide safety against TOCTOU conditions. Whether this will occur as an atomic operation depends on the OS and filesystem in use. In particular NFS versions below 3 do not support the needed operations for atomicity.
Unlike the Rust stdlib, an options with write set to
OpenOptionsWriteMode::None can still be used to create a new file.
use fs_at::OpenOptions;
let file = OpenOptions::default().write(OpenOptionsWriteMode::Write)
.create_new(true)
.open_at(&mut parent, "foo.txt");
let f = OpenOptions::default()
.open_at(&mut parent, "foo.txt").unwrap_err();
sourcepub fn follow(&mut self, follow: bool) -> &mut Self
pub fn follow(&mut self, follow: bool) -> &mut Self
Set the option to follow symlinks
This defaults to true, matching the behaviour of syscalls and most command line utilities - except for mkdir
Unix: This corresponds to O_NOFOLLOW, which disables symlink resolution only for the last element of a path.
Windows: This corresponds to controlling FILE_FLAG_OPEN_REPARSE_POINT, which behaves similarly.
sourcepub fn mkdir_at<P: AsRef<Path>>(&self, d: &File, p: P) -> Result<File>
pub fn mkdir_at<P: AsRef<Path>>(&self, d: &File, p: P) -> Result<File>
Create a directory relative to an open directory. Errors if a rooted path is provided.
Returns a File opened on the created directory.
Platform specific:
- on Windows, atomically creates a new directory (two syscalls: one to create the directory with link following disabled, and one to probe whether the opened directory is itself a link).
- on Unix, treats EEXIST as an error, but on success requires a separate
openatsyscall to open the created directory. This limitation may be lifted in future if the mooted mkdirat2 call gets created.. The mode of the new directory defaults to 0o777.
sourcepub fn open_at<P: AsRef<Path>>(&self, d: &File, p: P) -> Result<File>
pub fn open_at<P: AsRef<Path>>(&self, d: &File, p: P) -> Result<File>
Opens a file at the path p relative to the directory d.
This will honour the options set for creation/append etc, but will only operate relative to d. To open a file with an absolute path, use the stdlib fs::OpenOptions.
Platform specific:
Windows: Backed by
NTCreateFile.
This function does not perform file name separator translations. If
passing a path containing a separator, it must be a platform native one.
e.g. foo\\bar on Windows, vs foo/bar on most other OS’s. This
function cannot open the parent directory (e.g. open_at(&d, “..”)). It
is possible for callers to determine the path of a
handle,
and then open that using normal stdlib functions.
Unix: Backed by openat(2).
sourcepub fn open_dir_at<P: AsRef<Path>>(&self, d: &File, p: P) -> Result<File>
pub fn open_dir_at<P: AsRef<Path>>(&self, d: &File, p: P) -> Result<File>
Opens a directory.
This is a thin layer over [open_at] which handles the platform specific variation involved in opening a directory. Follow handling is automatically disabled.
As with [open_at], extension methods can be used to override the underlying behaviour.
Platform specific:
Windows: sets FILE_FLAG_OPEN_REPARSE_POINT for createOptions, and for dwAccessFlag adds in FILE_LIST_DIRECTORY and FILE_TRAVERSE. Further, read and write requests are translated to FILE_READ_ATTRIBUTES, and FILE_WRITE_ATTRIBUTES|DELETE respectively.
Unix: sets O_NOFOLLOW
sourcepub fn symlink_at<P, Q>(
&self,
d: &File,
linkname: P,
entry_type: LinkEntryType,
target: Q
) -> Result<()>where
P: AsRef<Path>,
Q: AsRef<Path>,
pub fn symlink_at<P, Q>( &self, d: &File, linkname: P, entry_type: LinkEntryType, target: Q ) -> Result<()>where P: AsRef<Path>, Q: AsRef<Path>,
Creates a symlink at the path linkname pointing to target.
This will fail if the path linkname is already used.
Unlike [open_at] this doesn’t return a File object: opening symlink
files directly is not portable.
Note: on Windows two syscalls are required to create a symlink. The
creation of the backing file is atomic and safe, but it is possible if
the process is interrupted that it will remain as a an blank
LinkEntryType rather than being converted to a symlink.
https://github.com/rbtcollins/fs_at/issues/10
The target may be an absolute or relative path, and will be inspected to
determine that before creation - but as with [open_at] native OS path
separators must be used, and minimal processing is done - to use
absolute paths, canonicalise them first.
The entry_type is unused on *nix OS’s; if writing *nix only software,
just pass in LinkEntryType::default(). Similarly if writing portable
software where the only consumers will be symlink aware. But if humans
using a UI are expected to interact with the link, choose an appropriate
type based on how the UI should behave when viewing the parent.
Stability: it isn’t clear whether entry_type should be exposed, or the default should be just a file(or dir) always and then fine grained control via an extension trait.
sourcepub fn unlink_at<P>(&self, d: &File, p: P) -> Result<()>where
P: AsRef<Path>,
pub fn unlink_at<P>(&self, d: &File, p: P) -> Result<()>where P: AsRef<Path>,
Unlink a non-directory at a path relative to d.
If the path referred to is a symbolic link, the link itself is removed.
Platform specific: some platforms treat unlink and rmdir as equivalent. Others such as Mac OSX do not, and rmdir must be used when deleting a directory.