nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1use std::{
2 env,
3 io::{Write, stdout},
4 os::unix::ffi::OsStrExt,
5 os::unix::fs,
6 path::{Path, PathBuf},
7 process::Command,
8};
9
10use anyhow::{Context, Result, bail};
11
12/// Canonicalize `path` in a chroot at the specified `root`.
13pub fn canonicalize_in_chroot(root: &str, path: &Path) -> Result<PathBuf> {
14 let output = Command::new("chroot-realpath")
15 .arg(root)
16 .arg(path.as_os_str())
17 .output()
18 .context("Failed to run chroot-realpath. Most likely, the binary is not on PATH")?;
19
20 if !output.status.success() {
21 bail!(
22 "chroot-realpath exited unsuccessfully: {}",
23 String::from_utf8_lossy(&output.stderr)
24 );
25 }
26
27 let output =
28 String::from_utf8(output.stdout).context("Failed to decode stdout of chroot-realpath")?;
29
30 Ok(PathBuf::from(&output))
31}
32
33/// Entrypoint for the `chroot-realpath` binary.
34pub fn chroot_realpath() -> Result<()> {
35 let args: Vec<String> = env::args().collect();
36
37 if args.len() != 3 {
38 bail!("Usage: {} <chroot> <path>", args[0]);
39 }
40
41 fs::chroot(&args[1]).context("Failed to chroot")?;
42 std::env::set_current_dir("/").context("Failed to change directory")?;
43
44 let path = std::fs::canonicalize(&args[2])
45 .with_context(|| format!("Failed to canonicalize {}", args[2]))?;
46
47 stdout()
48 .write_all(path.into_os_string().as_bytes())
49 .context("Failed to write output")?;
50
51 Ok(())
52}