obliterate 1.2.0

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

๐Ÿ” 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.2"

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

๐Ÿ’ก 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 four-tier strategy:

  1. umount2(MNT_DETACH) โ€” Direct syscall via libc.
  2. User Namespace Fork โ€” Creates a temporary user/mount namespace to unmount without root privileges.
  3. fusermount3 -u -z โ€” Fallback for FUSE mounts.
  4. fusermount -u -z โ€” Legacy fallback.

Mounts are processed deepest-first to ensure children are detached before their parents. If unmounting fails, an error is returned and deletion is aborted to avoid leaving orphaned filesystems behind.

๐Ÿงต Recursive removal

The crate recursively deletes files and directories while:

  • Fixing permissions on-the-fly to allow deletion of read-only items.
  • Avoiding stack overflow via stacker for extremely deep trees.
  • Normalizing paths and validating they don't escape the intended target.

โ— Error variants

pub enum Error {
    /// OS-level I/O failure.
    Io(std::io::Error),

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

๐Ÿ“œ 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