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_dir is 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

source

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");
source

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");
source

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");
source

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.
source

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();
source

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.

source

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 openat syscall 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.
source

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).

source

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

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.

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.

source

pub fn rmdir_at<P>(&self, d: &File, p: P) -> Result<()>where P: AsRef<Path>,

Remove a directory at a path relative to d.

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.

Trait Implementations§

source§

impl Debug for OpenOptions

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for OpenOptions

source§

fn default() -> OpenOptions

Returns the “default value” for a type. Read more
source§

impl OpenOptionsExt for OpenOptions

source§

fn mode(&mut self, mode: mode_t) -> &mut Self

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.