lcpfs 2026.1.102

LCP File System - A ZFS-inspired copy-on-write filesystem for Rust
// Copyright 2025 LunaOS Contributors
// SPDX-License-Identifier: Apache-2.0

//! # Trash / Recycle Bin
//!
//! Move deleted files to trash instead of permanent deletion.
//!
//! ## Overview
//!
//! This module provides recycle bin functionality for LCPFS, allowing
//! files to be recovered after deletion.
//!
//! ## Example
//!
//! ```rust,ignore
//! use lcpfs::trash::{Trash, TrashFilter};
//!
//! // Delete file to trash
//! let trash_id = Trash::delete("pool/data", "/important.doc")?;
//!
//! // List trash contents
//! let items = Trash::list("pool/data")?;
//! for item in items {
//!     println!("{} (deleted {}s ago)", item.original_path, now() - item.deleted_at);
//! }
//!
//! // Restore file
//! Trash::restore("pool/data", trash_id, None)?;
//!
//! // Empty old trash
//! Trash::empty("pool/data", TrashFilter::OlderThan(7 * 24 * 3600))?;
//! ```

mod ops;
mod types;

pub use ops::*;
pub use types::*;

use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use lazy_static::lazy_static;
use spin::Mutex;

lazy_static! {
    /// Per-dataset trash metadata
    static ref TRASH_METADATA: Mutex<BTreeMap<String, TrashMetadata>> = Mutex::new(BTreeMap::new());
    /// Per-dataset trash configuration
    static ref TRASH_CONFIG: Mutex<BTreeMap<String, TrashConfig>> = Mutex::new(BTreeMap::new());
}

/// Trash / Recycle Bin interface
pub struct Trash;

impl Trash {
    /// Delete a file or directory to trash
    ///
    /// Returns the trash ID which can be used for restoration.
    pub fn delete(dataset: &str, path: &str) -> Result<u64, TrashError> {
        trash_delete(dataset, path)
    }

    /// Restore a file from trash
    ///
    /// If `target_path` is None, restores to original location.
    pub fn restore(
        dataset: &str,
        trash_id: u64,
        target_path: Option<&str>,
    ) -> Result<(), TrashError> {
        trash_restore(dataset, trash_id, target_path)
    }

    /// List all items in trash
    pub fn list(dataset: &str) -> Result<Vec<TrashEntry>, TrashError> {
        trash_list(dataset)
    }

    /// Empty trash (permanent deletion)
    pub fn empty(dataset: &str, filter: TrashFilter) -> Result<TrashEmptyResult, TrashError> {
        trash_empty(dataset, filter)
    }

    /// Get total size of trash
    pub fn size(dataset: &str) -> Result<u64, TrashError> {
        trash_size(dataset)
    }

    /// Configure trash for a dataset
    pub fn configure(dataset: &str, config: TrashConfig) -> Result<(), TrashError> {
        set_trash_config(dataset, config)
    }

    /// Get trash configuration for a dataset
    pub fn get_config(dataset: &str) -> TrashConfig {
        get_trash_config(dataset)
    }

    /// Permanently delete without using trash
    pub fn permanent_delete(dataset: &str, path: &str) -> Result<(), TrashError> {
        permanent_delete(dataset, path)
    }

    /// Check if a path is in trash
    pub fn is_in_trash(dataset: &str, path: &str) -> bool {
        path.contains(TRASH_DIR)
    }
}

/// Trash directory name
pub const TRASH_DIR: &str = ".lcpfs_trash";
/// Trash items subdirectory
pub const TRASH_ITEMS: &str = "items";
/// Trash metadata file
pub const TRASH_METADATA_FILE: &str = "metadata.json";