nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 111 lines 3.8 kB view raw
1use std::{ 2 fs, 3 path::{Path, PathBuf}, 4}; 5 6use anyhow::{Context, Result}; 7 8use crate::{config::Config, fs::atomic_symlink}; 9 10/// Activate the system. 11/// 12/// This runs both during boot and during re-activation initiated by switch-to-configuration. 13pub fn activate(prefix: &str, toplevel: impl AsRef<Path>, config: &Config) -> Result<()> { 14 log::info!("Setting up /run/current-system..."); 15 let system_path = PathBuf::from(prefix).join("run/current-system"); 16 atomic_symlink(&toplevel, system_path)?; 17 18 log::info!("Setting up modprobe..."); 19 setup_modprobe(&config.modprobe_binary)?; 20 21 log::info!("Setting up firmware search paths..."); 22 setup_firmware_search_path(&config.firmware)?; 23 24 if let Some(env_path) = &config.env_binary { 25 log::info!("Setting up /usr/bin/env..."); 26 setup_usrbinenv(prefix, env_path)?; 27 } else { 28 log::info!("No env binary provided. Not setting up /usr/bin/env."); 29 } 30 31 if let Some(sh_path) = &config.sh_binary { 32 log::info!("Setting up /bin/sh..."); 33 setup_binsh(prefix, sh_path)?; 34 } else { 35 log::info!("No sh binary provided. Not setting up /bin/sh."); 36 } 37 38 Ok(()) 39} 40 41/// Setup modprobe so that the kernel can find the wrapped binary. 42/// 43/// See <https://docs.kernel.org/admin-guide/sysctl/kernel.html#modprobe> 44fn setup_modprobe(modprobe_binary: impl AsRef<Path>) -> Result<()> { 45 // This uses the procfs setup in the initrd, which is fine because it points to the same kernel 46 // a procfs in a chroot would. 47 const MODPROBE_PATH: &str = "/proc/sys/kernel/modprobe"; 48 49 if Path::new(MODPROBE_PATH).exists() { 50 fs::write( 51 MODPROBE_PATH, 52 modprobe_binary.as_ref().as_os_str().as_encoded_bytes(), 53 ) 54 .with_context(|| { 55 format!( 56 "Failed to populate modprobe path with {}", 57 modprobe_binary.as_ref().display() 58 ) 59 })?; 60 } else { 61 log::info!("{MODPROBE_PATH} doesn't exist. Not populating it..."); 62 } 63 64 Ok(()) 65} 66 67/// Setup the firmware search path so that the kernel can find the firmware. 68/// 69/// See <https://www.kernel.org/doc/html/latest/driver-api/firmware/fw_search_path.html> 70fn setup_firmware_search_path(firmware: impl AsRef<Path>) -> Result<()> { 71 // This uses the sysfs setup in the initrd, which is fine because it points to the same kernel 72 // a procfs in a chroot would. 73 const FIRMWARE_SERCH_PATH: &str = "/sys/module/firmware_class/parameters/path"; 74 75 if Path::new(FIRMWARE_SERCH_PATH).exists() { 76 fs::write( 77 FIRMWARE_SERCH_PATH, 78 firmware.as_ref().as_os_str().as_encoded_bytes(), 79 ) 80 .with_context(|| { 81 format!( 82 "Failed to populate firmware search path with {}", 83 firmware.as_ref().display() 84 ) 85 })?; 86 } else { 87 log::info!("{FIRMWARE_SERCH_PATH} doesn't exist. Not populating it..."); 88 } 89 90 Ok(()) 91} 92 93/// Setup `/usr/bin/env`. 94/// 95/// We have to setup `/usr` for `NixOS` to work. 96/// 97/// We do this here accidentally. `/usr/bin/env` is currently load-bearing for `NixOS`. 98fn setup_usrbinenv(prefix: &str, env_binary: impl AsRef<Path>) -> Result<()> { 99 let usrbin_path = PathBuf::from(prefix).join("usr/bin"); 100 fs::create_dir_all(&usrbin_path).context("Failed to create /usr/bin")?; 101 atomic_symlink(&env_binary, usrbin_path.join("env")) 102} 103 104/// Setup /bin/sh. 105/// 106/// `/bin/sh` is an essential part of a Linux system as this path is hardcoded in the `system()` call 107/// from libc. See `man systemd(3)`. 108fn setup_binsh(prefix: &str, sh_binary: impl AsRef<Path>) -> Result<()> { 109 let binsh_path = PathBuf::from(prefix).join("bin/sh"); 110 atomic_symlink(&sh_binary, binsh_path) 111}