# pseudoroot
[](LICENSE-MIT)
[](https://github.com/lu-zero/pseudoroot/actions?query=workflow:CI)
[](https://deps.rs/repo/github/lu-zero/pseudoroot)
A Rust implementation of fakeroot using library interposition
(`LD_PRELOAD` on Linux, `DYLD_INSERT_LIBRARIES` on macOS). Commands run as
if they had root privileges without requiring real root access.
## Quick start
```bash
cargo install --path pseudoroot
# Implicit run (fakeroot-style)
pdr -- id
# Explicit subcommand form (equivalent)
pdr run -- id
pdr --uid 1000 --gid 1000 -- id
```
`pdr` is a single self-contained binary — the interposed library is embedded
at build time and extracted to a cache directory on first use, so no
`libpseudoroot_lib.so`/`.dylib` needs to exist anywhere on disk beforehand.
`pdr start` runs the optional persistent daemon in-process, so no separate
`pdrd` binary is needed for that either; a standalone `pdrd` is still
available (see [Build and test](#build-and-test)) as a dedicated daemon
process for external orchestration.
## CLI options
| `--uid <UID>` | Fake UID | 0 |
| `--gid <GID>` | Fake GID | 0 |
| `--daemon` | Attach to an existing `pdrd` instead of a per-invocation session | off |
| `--socket-path <PATH>` | Daemon socket path | `/tmp/pseudoroot.sock` |
| `start` / `stop` / `status` | Manage the daemon | — |
| `print-library-path` | Print the interposed library path | — |
| `start --verbose` | Enable verbose daemon logging | off |
| `start --cleanup` | Clean up socket file on daemon exit | off |
By default each invocation gets its own session, shared across `exec`
within it. To share state across separate invocations, use a daemon:
```bash
pdr start --socket-path /tmp/pseudoroot.sock # daemon runs in-process
pdr --daemon --socket-path /tmp/pseudoroot.sock -- make install
pdr stop --socket-path /tmp/pseudoroot.sock
```
## Rust API (fakeroost-compatible)
Swap backends by changing the import only:
```rust
use pseudoroot::FakerootCommandExt;
fn main() {
pseudoroot::init(); // required: handles session re-exec (no-op otherwise)
std::process::Command::new("make")
.arg("install")
.env("PSEUDOROOT_UID", "0")
.env("PSEUDOROOT_GID", "0")
.fakeroot()
.status()
.unwrap();
}
```
## Environment variables
- `PSEUDOROOT_UID` / `PSEUDOROOT_GID` — fake uid/gid (default: 0)
- `PSEUDOROOT_DAEMON_SOCKET` — attach to an existing daemon (skips session auto-start)
- `PSEUDOROOT_STANDALONE` — per-process state only (no session)
- `PSEUDOROOT_SESSION_SHM` — set to `0` to use an in-process daemon thread instead of the shared-memory map for session mode
- `PSEUDOROOT_LIB` — override the interposed library path, bypassing the
embedded copy entirely (tests, custom installs, debugging a locally built
`pseudoroot-lib`)
## Documentation
- [Architecture](docs/architecture.md) — crate layout, inode-keyed state
model, platform support, interposed syscall families.
- [Benchmarks](docs/benchmarks.md) — comparison against native,
`fakeroot`, and `fakeroost`; on a 128-core Linux machine pseudoroot sustains
~7.4M faked `stat()` calls/sec vs fakeroot's ~44.5K, and on a MacBook Pro
with M2 Max (12-core ARM64) ~899K calls/sec vs fakeroot's ~43K.
## Comparison
| Mechanism | `LD_PRELOAD` | `LD_PRELOAD` | ptrace supervisor |
| Platforms | Linux, macOS | Linux | Linux |
| xattr / setcap | Faked | Faked | Faked |
| mknod unprivileged | Placeholder + fake metadata | Yes | Yes |
| Multi-process state | SHM session or daemon (`pdrd`) | `faked` | N/A (single run) |
| Rust API | `FakerootCommandExt` | C only | `FakerootCommandExt` |
## Build and test
```bash
cargo build
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --check
```
`pdr` embeds the interposed library at build time: `pseudoroot/build.rs`
compiles the cdylib from the source bundled at `pseudoroot/interpose/` and
`include_bytes!`es it into the binary — so `cargo install pseudoroot` from
crates.io is self-contained, with no separate `.so`/`.dylib` to install.
For a standalone `pdrd` daemon binary, build the `pseudoroot-daemon` package
directly: `cargo build -p pseudoroot-daemon`.
## License
Licensed under [MIT](LICENSE-MIT).
## Contributing
See [AGENTS.md](./AGENTS.md) for conventions (Conventional Commits, style,
MSRV checks).
## Author
Luca Barbato <lu_zero@gentoo.org>