mmap-guard 0.2.0

Safe, guarded memory-mapped file I/O for Rust
Documentation

mmap-guard

GitHub License GitHub Sponsors

GitHub Actions Workflow Status docs.rs Deps.rs Repository Dependencies

Codecov GitHub issues GitHub last commit

Crates.io Crates.io MSRV


OpenSSF Scorecard


Safe, guarded memory-mapped file I/O for Rust. Wraps memmap2::Mmap::map() behind a safe API so downstream crates can use #![forbid(unsafe_code)] while still benefiting from zero-copy file access.

Why mmap-guard?

Projects that enforce #![forbid(unsafe_code)] cannot call memmap2::Mmap::map() directly because it is unsafe. The alternative — std::fs::read() — copies the entire file into heap memory, which is impractical for disk images and multi-gigabyte binaries.

mmap-guard bridges this gap by isolating the unsafe boundary in a single, focused crate. By centralizing it here, we can concentrate testing, fuzzing, and hardening efforts on that one point — so every consumer benefits from those protections without reasoning about mmap safety themselves.

Features

  • Safe mmap construction — wraps memmap2::Mmap::map() with pre-flight checks (empty file detection, permission errors)
  • Advisory file locking — acquires a shared advisory lock (via fs4) before mapping; returns io::ErrorKind::WouldBlock on lock contention
  • Platform quirk mitigation — documents and (where possible) mitigates SIGBUS/access violations from file truncation
  • Unified read API — returns &[u8] whether backed by mmap or a heap buffer (for stdin/non-seekable inputs)
  • Zero unsafe for consumers — exactly one unsafe block, fully documented with a // SAFETY: comment
  • Minimal dependenciesmemmap2 and fs4 at runtime

Quick Start

Installation

Add to your Cargo.toml:

[dependencies]
mmap-guard = "0.1"

Usage

use mmap_guard::map_file;

// Memory-map a file — returns FileData that derefs to &[u8]
let data = map_file("large-file.bin")?;
assert!(!data.is_empty());
// Use it like any byte slice
println!("first byte: {:#04x}", data[0]);

For CLI tools that accept both file paths and stdin:

use mmap_guard::load;

// load() handles both file paths and stdin ("-" with a 1 GiB default cap).
let data = load("input.txt")?;

// For a custom stdin byte limit, call load_stdin directly:
// use mmap_guard::load_stdin;
// let data = load_stdin(Some(10 * 1024 * 1024))?; // 10 MiB cap
// let data = load_stdin(None)?;                    // unlimited

Architecture

graph TD
    load["load(path)"] -->|path == "-"| load_stdin
    load -->|other paths| map_file
    load_stdin["load_stdin(max_bytes)"] --> FileData
    map_file["map_file()"] --> unsafe["unsafe { Mmap::map() }"]
    unsafe --> FileData["FileData<br/>Deref&lt;Target=[u8]&gt;"]
    FileData --- Mapped["Mapped(Mmap, File)"]
    FileData --- Loaded["Loaded(Vec&lt;u8&gt;)"]
Module Purpose
src/lib.rs Crate-level docs, re-exports public API
src/map.rs map_file() with pre-flight stat check; the single unsafe block
src/load.rs load() routes "-" to load_stdin(), others to map_file()
src/file_data.rs FileData enum (Mapped(Mmap, File) / Loaded), Deref, AsRef

What It Does NOT Do

  • Provide mutable/writable mappings
  • Abstract over async I/O
  • Implement its own mmap syscalls (delegates entirely to memmap2)

Safety

This crate contains exactly one unsafe block — the call to memmap2::Mmap::map(). The safety contract is maintained through:

  • File opened read-only (File::open())
  • Shared advisory lock acquired via fs4 before mapping — contention returns io::ErrorKind::WouldBlock
  • File descriptor and lock held through ownership in FileData::Mapped(Mmap, File) — released on drop
  • No mutable aliasing (read-only mappings only)
  • #![deny(clippy::undocumented_unsafe_blocks)] enforced

See the safety documentation for the full contract and known limitations (SIGBUS from concurrent file truncation).

Security

  • Strict linting — pedantic/nursery/cargo clippy groups, unwrap_used denied, panic denied
  • Dependency auditingcargo audit and cargo deny in CI
  • Coverage threshold — 80%+ project coverage enforced
  • Supply chain — OpenSSF Scorecard monitoring

Documentation

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

Licensed under either of Apache License 2.0 or MIT License, at your option.

Acknowledgments

  • memmap2 for the underlying memory-mapping implementation
  • The Rust community for excellent tooling and ecosystem