Skip to main content

DirHandle

Trait DirHandle 

Source
pub trait DirHandle:
    Sized
    + Send
    + Sync
    + Sealed {
    type Attrs: Copy;

Show 14 methods // Required methods fn open_root(path: &Path) -> Result<Self, GuardIo>; fn open_child_dir(&self, name: &OsStr) -> Result<Self, GuardIo>; fn make_child_dir(&self, name: &OsStr) -> Result<(), GuardIo>; fn open_child_file( &self, name: &OsStr, mode: OpenMode, ) -> Result<File, GuardIo>; fn create_child_file( &self, name: &OsStr, excl: Excl, ) -> Result<File, GuardIo>; fn rename_child(&self, from: &OsStr, to: &OsStr) -> Result<(), GuardIo>; fn unlink_child(&self, name: &OsStr); fn child_kind(&self, name: &OsStr) -> Option<NodeKind>; fn child_attrs(&self, name: &OsStr) -> Option<Self::Attrs>; fn apply_attrs(&self, file: &File, attrs: Self::Attrs) -> Result<()>; fn identity(&self) -> Result<NodeId, GuardIo>; fn resolve_beneath( &self, rel: &Path, mode: OpenMode, ) -> Result<Option<File>, GuardIo>; fn into_file(self) -> File ; fn sync_name_durability(&self) -> Result<(), GuardIo>;
}
Expand description

A directory the caller already proved is inside the guard root, and the only way to go one step deeper.

INVARIANT, enforced by the type and not by review: no method accepts an absolute path, and no method accepts a multi-component path. Every operation names one component, relative to self. That is what makes fsguard’s one-door property structural — code handed a DirHandle still cannot reach outside it, which is strictly stronger than free functions, where nothing but discipline stops a second open() on a full path.

The one exception proves the rule: resolve_beneath takes a multi-component relative path, and the whole point of it is that the kernel enforces beneath-ness in a single syscall. It is not a weakening of the invariant, it is the invariant delegated to the one place that can honor it atomically.

Sealed, because the guarantees above are statements about all implementors.

Required Associated Types§

Source

type Attrs: Copy

Attributes worth carrying across an atomic replace. Unix: the mode, so editing a script does not silently drop its executable bit. Windows: the FILE_ATTRIBUTE_* bits, where read-only and hidden play the same role. Not a shared shape, because there is no shared shape to have.

Required Methods§

Source

fn open_root(path: &Path) -> Result<Self, GuardIo>

Open the guard root itself, by name. The root is ours, not the model’s — this is the only place a full path enters, and it is the anchor every other method is relative to.

Source

fn open_child_dir(&self, name: &OsStr) -> Result<Self, GuardIo>

Open a child directory without following any link at the final component. Unix O_NOFOLLOW|O_DIRECTORY; Windows FILE_OPEN_REPARSE_POINT|FILE_DIRECTORY_FILE relative to the handle.

Source

fn make_child_dir(&self, name: &OsStr) -> Result<(), GuardIo>

mkdirat. Succeeding when it already exists is the caller’s business, not this method’s.

Source

fn open_child_file(&self, name: &OsStr, mode: OpenMode) -> Result<File, GuardIo>

Source

fn create_child_file(&self, name: &OsStr, excl: Excl) -> Result<File, GuardIo>

Source

fn rename_child(&self, from: &OsStr, to: &OsStr) -> Result<(), GuardIo>

Best-effort removal of our own temp file. A failure here has nothing to report, which is why it returns nothing.

Source

fn child_kind(&self, name: &OsStr) -> Option<NodeKind>

Classify a child without following it, or None if it does not exist. See NodeKind — the fail-closed default is the whole point.

Source

fn child_attrs(&self, name: &OsStr) -> Option<Self::Attrs>

Source

fn apply_attrs(&self, file: &File, attrs: Self::Attrs) -> Result<()>

Source

fn identity(&self) -> Result<NodeId, GuardIo>

Stable identity, for the belt-and-braces check that the handle we validated and the path we return are the same object.

Source

fn resolve_beneath( &self, rel: &Path, mode: OpenMode, ) -> Result<Option<File>, GuardIo>

Single-syscall beneath-resolution where the OS has one: Linux openat2 with RESOLVE_BENEATH|RESOLVE_NO_SYMLINKS|RESOLVE_NO_MAGICLINKS, Windows NtCreateFile with OBJ_DONT_REPARSE.

Ok(None) means this kernel does not offer it (pre-5.6 Linux, a seccomp filter returning ENOSYS/EPERM, pre-1607 Windows) and the caller must fall through to the component-wise descent. It does not mean “allowed” — an actual refusal is Err.

Source

fn into_file(self) -> File

Hand back the handle for this directory itself, for the one case where the caller’s target is the directory it already descended to. Widens nothing: it returns the object the caller already holds.

Source

fn sync_name_durability(&self) -> Result<(), GuardIo>

After this returns, the most recent rename in this directory survives a crash.

CONTRACT is the guarantee, not the mechanism, and the two platforms reach it differently: Unix must fsync the directory fd, because without it the rename can be lost even though the data was synced. NTFS journals the metadata operation itself, so on Windows the guarantee already holds when the rename returns. Windows returning Ok is therefore a claim that the property is satisfied — not a no-op standing in for a capability the platform lacks.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§