#permissions #rm #remove

obliterate

Force-remove Files and Directories on Linux Including Paths with 000 Permissions

3 stable releases

Uses new Rust 2024

new 1.1.0 Apr 14, 2026
1.0.1 Apr 12, 2026

#975 in Filesystem

MIT license

34KB
546 lines

๐Ÿ’ฅ Obliterate - Force Removal on Linux

Force-remove Files and Directories on Linux Including Paths with 000 Permissions.

๐Ÿ” Overview

obliterate is a Linux-only Rust crate designed to aggressively and safely remove files and directories โ€” even in scenarios where traditional tools fail. It handles edge cases like 000 permissions, nested mount points, and deeply recursive trees without stack overflows.

Unlike traditional approaches, this crate:

  • Fixes permissions automatically before deletion;
  • Detects and lazily unmounts nested mount points;
  • Avoids dangerous path patterns like ..;
  • Uses controlled recursion with stack growth protection;

๐Ÿš€ Features

  • ๐Ÿ”’ Handles 000 permissions
    removes trees that std::fs::remove_dir_all cannot.

  • ๐Ÿงฉ Mount-point aware
    lazily unmounts nested filesystems before deleting.

  • ๐Ÿงฑ Stack-safe recursion
    uses stacker to safely handle deeply nested trees.

  • ๐Ÿ›ก๏ธ Basic safety guards
    prevents invalid paths like ...

  • ๐Ÿ“ฆ Structured errors
    clear error types for invalid targets, I/O failures, and unmount issues.

  • ๐Ÿง Linux-only
    relies on /proc/self/mountinfo and umount2.

๐Ÿ“– Usage

This section demonstrates how to integrate and use obliterate in your Rust project. The crate provides two main entry points:

  • remove โžœ strict removal (fails if the path does not exist)
  • ensure_removed โžœ forgiving removal (behaves like rm -rf)

Add the dependency to your Cargo.toml:

[dependencies]
obliterate = "1.0"

Then use it in your code:

use obliterate::{remove, ensure_removed, Error};

// Strict removal (fails if not found)
remove("target")?;

// Idempotent removal (like rm -rf)
ensure_removed("build")?;

match remove("some/path") {
    Ok(()) => {}
    Err(Error::NotFound) => eprintln!("already gone"),
    Err(Error::UnmountFailed { path, fstype, reason }) => {
        eprintln!("failed to unmount {} ({}): {}", path.display(), fstype, reason)
    }
    Err(e) => return Err(e.into()),
}

๐Ÿ’ก When to use each function

  • Use remove when you expect the path to exist and want strict error handling.
  • Use ensure_removed when you want idempotent cleanup, especially in build scripts, CI pipelines, or temporary directory management.

Both functions guarantee safe, race-resistant removal using file-descriptor-based operations under the hood.

โš™๏ธ How it works

๐Ÿ”“ Permission handling

Before deletion, the crate ensures the current process has sufficient permissions by setting mode 0o700 when necessary. std::fs::remove_dir_all fails on directories with 000 permissions because the kernel checks execute permission on the directory before allowing iteration.

๐Ÿงท Mount-point handling

Before touching any directory, obliterate reads /proc/self/mountinfo and collects every mount-point nested inside the target tree. They are unmounted deepest-first using a three-tier strategy:

  1. umount2(MNT_DETACH) via libc
  2. fusermount3 -u -z
  3. fusermount -u -z

Mounts are processed deepest-first to avoid dependency issues. If unmounting fails, an error is returned and deletion is aborted.

๐Ÿงต Recursive removal

The crate recursively deletes files and directories while:

  • Fixing permissions
  • Avoiding stack overflow via stacker
  • Handling both files and directories correctly

โ— Error variants

pub enum Error {
    /// Path does not exist (only from `remove`, not `ensure_removed`).
    NotFound,

    /// The Path ends in ".." or is otherwise invalid.
    InvalidTarget(String),

    /// OS-level I/O failure, with the path that triggered it.
    IoError(std::io::Error),

    /// A nested mount-point could not be unmounted.
    UnmountFailed {
        path: PathBuf,
        fstype: String,
        reason: String,
    },
}

๐Ÿงช Notes

Some unmount operations may require elevated privileges (CAP_SYS_ADMIN).

๐Ÿ“œ MIT License

This repository has scripts created to be free software.
Therefore, they can be distributed and/or modified within the terms of the MIT License.

See the MIT License file for details.

๐Ÿ“ฌ Contact

Dependencies

~0.2โ€“10MB
~61K SLoC