Dir

Struct Dir 

Source
pub struct Dir { /* private fields */ }
Expand description

A owned reference to an opened directory. This reference is automatically cleaned up on drop.

Implementations§

Source§

impl Dir

Source

pub fn open<P: AsRef<Path>>(path: P) -> Result<Self>

Opens the directory using a normal open(2) syscall.

This does not follow symbolic links.

Source

pub fn open_virtual<P: AsRef<Path>>(path: P) -> Result<Self>

Opens the directory using a normal open(2) syscall and the O_PATH option.

This means the file descriptor will not truly be opened; this requires less permissions on the directory itself and may be more efficient if only open_* methods are used on the Dir.

This will lead to some operations, like readdir, failing.

This does not follow symbolic links.

Source

pub fn with_flags(self, flags: i32) -> Self

Overrides the open flags used by Dir::open_dirs or Dir::open_file. Use flags prefixed by O_ in libc.

When opening directories, the O_RDONLY flags is always used.

§Important flags

O_NOFOLLOW: This flag prevents symlinks from being followed. Handling symlinks in a race-condition free way can be tedious and heavily depends on your use case; it is therefore recommended to never follow symlinks.

O_PATH: Using this flag means the file or directory won’t actually be opened; the resulting file descriptor can only be used by *at syscalls (like with the Dir::open_dirs and Dir::open_file methods) and other limited scenarios. Files and directories with this flag will not be able to be read, written to and other file operations won’t be available, including changing ownership of the file. Using this flag can lessen filesystem load in some cases, by not updating atime for example. Note this flag is not available on MacOS systems.

§Example
use sneak::{default_flags, Dir};
use libc::O_PATH;

// open ./db/data.bin without modifying their `atime`, free of race conditions and
// traversal attacks.
let data_file = Dir::open(base_path)?
    .with_flags(default_flags() | O_PATH)
    .open_file("./db/data.bin")
Source

pub fn flags(&self) -> i32

Returns the flags currently used by this Dir.

Source

pub fn fd(&self) -> i32

Returns the inner file descriptor held by the Dir. Shoudl only be used for debugging purposes; do not use the file descriptor outside Dir.

Source

pub fn open_dirs_beneath<P: AsRef<Path>>(&self, path: P) -> Result<Dir>

Opens the directory at the target path using the RESOLVE_BENEATH option of the openat2 syscall.

This prevents any component isn’t a descendent of the self directory. This prevents basic symlink traversal attacks by ensuring the resulting canonical path is always beneath the self directory in a race condition-safe way.

§Example
use sneak::Dir;

let basedir = Dir::open("/var/lib/myapplication/")?;
let res = basedir.open_dirs_beneath("user/path/../../..");

assert!(res.is_err());
Source

pub fn open_dirs_beneath_with_mode<P: AsRef<Path>>( &self, path: P, mode: u64, ) -> Result<Dir>

Like open_dirs_beneath, but allows you to specify a mode. This is useful if you want to use the O_CREAT flag:

use sneak::{default_flags, Dir};
use libc::O_CREAT;

// Note the `O_RDONLY` flag is always OR-ed for operations with directories
let root = Dir::open(".")?.with_flags(default_flags() | O_CREAT);
let data = root.open_dirs_beneath_with_mode("application/data", 0o655)?;

Note in this case the application will not be created if it doesn’t exist, only the data directory will: use open_dirs_with_mode with the O_CREAT flag instead.

Source

pub fn open_dirs_with_params<P: AsRef<Path>>( &self, path: P, open_how: &OpenHow, ) -> Result<Dir>

Opens a directory relative to self using the provided params directly to openat2. Note this will thus ignore the flags set on self.

§Example
use sneak::{default_flags, Dir, OpenHow};
use libc::{RESOLVE_NO_XDEV, O_CREAT};

let root = Dir::open("...")?;
let mut how = OpenHow::zeroed();
how.flags = default_flags() | O_CREAT;
how.mode = 0o655;
how.resolve = RESOLVE_NO_XDEV;

let result = root.open_dirs_with_params("subdirectory", &how);
Source

pub fn open_dirs<P: AsRef<Path>>(&self, path: P) -> Result<Dir>

Recursively opens every directory in the given path, returning the first encountered error or the leaf directory.

Note that:

  • Prefix (..) components are respected and saturate if they recurse behind the current directory (i.e. ./dir/../../../subdir just resolves to ./subdir.)
  • Current directory (.) and root directory prefixes (leading /) components are ignored.
  • Windows-specific path components raise a NotFound error.

Note the original directory self is kept open until it is dropped.

Symbolic links are not followed unless you’ve overridden the flags with Dir::with_flags to not contain O_NOFOLLOW.

§Example
use sneak::Dir;

// open directories ./user/store/data in `base_path`, free of race conditions and traversal attacks.
let dir = Dir::open(base_path)?.open_dirs("./user/store/data")?;
Source

pub fn open_dirs_with_mode<P: AsRef<Path>>( &self, path: P, mode: i32, ) -> Result<Dir>

Like open_dirs, but allows you to set a mode. Use this if you use the O_CREAT flag, else they will be created with file mode bits set to 0.

Source

pub fn open_file<P: AsRef<Path>>( &self, path: P, extra_flags: i32, mode: u64, ) -> Result<File>

Recursively opens every directory in the given path, then opens the last component as a file, returning the file handle or the first error.

The same path component rules as Dir::open_dirs are applied, with the exception that the last component of the path must be a normal component (not a prefix .. or current directory . component) and is treated as a file. The input path must also not be empty. If one of these conditions is violated, this returns IsADirectory or NotFound.

When opening the file, default flags or flags set with Dir::with_flags are used, except the O_DIRECTORY flags which is removed.

These flags are bit-ORed with the extra_flags argument, which is meant for file opening-specific flags like O_WRONLY. You may use flags such as O_CREAT or O_EXCL, but you must specify at least one of O_RDONLY, O_WRONLY or O_RDWR.

The mode argument will be used by every openat syscall.

§Example
use sneak::Dir;
use libc::{O_CREAT, O_WRONLY};

let dir = Dir::open(base_dir)?;

// open the file for writing, creating it if it doesn't exist
let mut file = dir.open_file("./subfolder/data.txt", O_CREAT | O_WRONLY)?;
file.write_all(my_data)?;
Source

pub fn fchown(&self, uid: u32, gid: u32) -> Result<()>

Changes ownership of the directory.

Note that, if you used the O_PATH flag with Dir::with_flags, this will always return an error.

§Example
use sneak::Dir;

let dir = Dir::open(base_dir)?.open_dirs("./data")?;

// change `./data` to be owned
dir.fchown(1000, 1000);
Source

pub fn fstat(&self) -> Result<Metadata>

Queries information about the directory.

Even if you used the O_PATH flag with Dir::with_flags, this should not return an error under normal circumstances.

§Example
use sneak::Dir;

let meta = Dir::open(base_dir)?.fstat()?;

// print the user ID and group ID of the owner of the directory
println!("uid({}) gid({})", meta.uid(), meta.gid())
Source

pub fn readdir(self) -> Result<DirStream>

Source

pub fn dup(&self) -> Result<Dir>

Trait Implementations§

Source§

impl Drop for Dir

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl Freeze for Dir

§

impl RefUnwindSafe for Dir

§

impl Send for Dir

§

impl Sync for Dir

§

impl Unpin for Dir

§

impl UnwindSafe for Dir

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

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 T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

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

Performs the conversion.
Source§

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

Source§

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

The type returned in the event of a conversion error.
Source§

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

Performs the conversion.