file-lock

POSIX advisory record file locking for Rust, with automatic unlock on drop.

Library
Cargo
v2.1.11
20stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
22/100Needs Attention
Development Activity0
Maintenance0
Community20
Maturity56
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
60/100Good
Architecture55
Code Quality65
Innovation75
Learning Curve45

file-lock is a small Rust crate that wraps POSIX advisory record locks (via fcntl()) behind a safe, ergonomic API. It lets a process take a blocking or non-blocking read or write lock on a file, coordinating access across multiple processes using the same UNIX locking primitives system tools have relied on for decades.

The crate exposes a single FileLock type returned from FileLock::lock(), built from a FileOptions builder that mirrors std::fs::OpenOptions. Locks are released automatically when the FileLock value is dropped, or explicitly via unlock(), making it straightforward to guard access to config files, PID files, or any shared resource that needs cross-process coordination without pulling in a heavier concurrency dependency.

What You Get

  • A FileLock type wrapping a locked std::fs::File, with the lock released automatically on Drop
  • A FileOptions builder mirroring std::fs::OpenOptions (read, write, append, create, create_new, truncate) plus lock-specific writeable tracking
  • Blocking and non-blocking lock acquisition via a single is_blocking flag passed to FileLock::lock()
  • A tiny C shim (file_lock.c) compiled via build.rs/cc that calls fcntl() directly for read (F_RDLCK) and write (F_WRLCK) advisory locks

Common Use Cases

  • Guarding a PID file or lock file so only one instance of a daemon or CLI tool runs at a time
  • Coordinating writes to a shared config or state file across multiple cooperating processes
  • Implementing simple cross-process mutexes for build scripts, cron jobs, or worker pools that share a filesystem
  • Serializing access to log files or append-only data files written by multiple processes

Under The Hood

Architecture The crate is deliberately thin: src/lib.rs defines the public FileLock struct and its lock/unlock/Drop behavior, delegating the actual locking to two extern "C" functions, c_lock and c_unlock, implemented in src/file_lock.c and compiled into a static library by build.rs using the cc crate. The FileOptions builder lives in its own module (src/file_options.rs) and is consumed by FileLock::lock, which opens the file, reads the writeable flag off the options, and passes the raw file descriptor into the C shim via AsRawFd. There is no abstraction beyond this single FFI boundary — changing the C locking strategy (e.g. swapping fcntl() for flock()) would only touch file_lock.c, while changing the builder’s surface would only touch file_options.rs.

Tech Stack Built for Rust 2021 edition with a single runtime dependency, libc 0.2.139, used for the c_int FFI type. The build pipeline compiles a small POSIX C file at build time via the cc 1.0.78 build-dependency, so any target must have a C toolchain (gcc) available. Dev-dependencies pull in nix 0.26.2 (process feature only) to exercise fork() in tests, simulating multi-process lock contention. There is no async runtime, framework, or database involved — it is a narrow systems-level binding intended to run on POSIX-compliant platforms.

Code Quality The crate ships in-module tests under #[cfg(test)] in lib.rs, including an exhaustive combinatorial matrix (nested loops over already-exists, already-locked, already-writable, blocking, and writable flags) that forks a child process per case to verify locking and contention behavior end to end, plus a focused read/write-only test. Error handling is idiomatic Rust: fcntl() return codes map to std::io::Error::from_raw_os_error, and the public API returns Result rather than panicking. Naming follows standard Rust conventions and mirrors std::fs::OpenOptions intentionally for familiarity. CI is configured via a .travis.yml file (Travis CI, not GitHub Actions), which is dated tooling and, combined with the repo’s inactive activity status and unreviewed open issues, suggests the project receives limited ongoing maintenance despite its solid original test coverage.

API Design The public surface is intentionally minimal: a single FileLock::lock(path, is_blocking, options) entry point and an optional explicit unlock(), with automatic unlocking on Drop removing an entire class of forgot-to-unlock bugs. FileOptions reuses std::fs::OpenOptions’ exact method names (read, write, append, create, create_new, truncate) so Rust developers already familiar with the standard library incur almost no learning curve. Doc comments throughout lib.rs include full, compilable usage examples for both lock and unlock, keeping the crate’s documentation self-contained even though it has no separate docs directory.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search