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
impl Dir
Sourcepub fn open<P: AsRef<Path>>(path: P) -> Result<Self>
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.
Sourcepub fn open_virtual<P: AsRef<Path>>(path: P) -> Result<Self>
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.
Sourcepub fn with_flags(self, flags: i32) -> Self
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")Sourcepub fn open_dirs_beneath<P: AsRef<Path>>(&self, path: P) -> Result<Dir>
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());Sourcepub fn open_dirs_beneath_with_mode<P: AsRef<Path>>(
&self,
path: P,
mode: u64,
) -> Result<Dir>
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.
Sourcepub fn open_dirs_with_params<P: AsRef<Path>>(
&self,
path: P,
open_how: &OpenHow,
) -> Result<Dir>
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);Sourcepub fn open_dirs<P: AsRef<Path>>(&self, path: P) -> Result<Dir>
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/../../../subdirjust resolves to./subdir.) - Current directory (
.) and root directory prefixes (leading/) components are ignored. - Windows-specific path components raise a
NotFounderror.
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")?;Sourcepub fn open_dirs_with_mode<P: AsRef<Path>>(
&self,
path: P,
mode: i32,
) -> Result<Dir>
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.
Sourcepub fn open_file<P: AsRef<Path>>(
&self,
path: P,
extra_flags: i32,
mode: u64,
) -> Result<File>
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)?;Sourcepub fn fchown(&self, uid: u32, gid: u32) -> Result<()>
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);Sourcepub fn fstat(&self) -> Result<Metadata>
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())