diff --git a/configs/crystal/install-base/up.nu b/configs/crystal/install-base/up.nu index ad03156..ebe9889 100644 --- a/configs/crystal/install-base/up.nu +++ b/configs/crystal/install-base/up.nu @@ -2,9 +2,4 @@ let REQUIRES_CHROOT = true; # Applies all system changes of `install-base` def main [cfg] { echo "Executing up task `install-base` with config" $cfg - ls /etc - cat /etc/mtab - pacman -S --noconfirm neofetch - neofetch - exit 1 } diff --git a/src/error.rs b/src/error.rs index 6246400..e4dd2d8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -105,6 +105,9 @@ pub enum ChrootError { #[error("Failed to remove symlink in chroot: {0}")] Unlink(io::Error), + #[error("Failed to copy file {0} to chroot: {1}")] + Copy(PathBuf, io::Error), + #[error("Failed to change process working directory: {0}")] ChDir(io::Error), } diff --git a/src/task/chrooting/mapping.rs b/src/task/chrooting/mapping.rs index 1f71ebf..75090bc 100644 --- a/src/task/chrooting/mapping.rs +++ b/src/task/chrooting/mapping.rs @@ -9,6 +9,8 @@ pub enum Mapping { Device(PathBuf), Dir(PathBuf, DirOpts), Special(PathBuf, PathBuf, DirOpts), + Link(PathBuf, PathBuf), + Copy(PathBuf, PathBuf), } #[derive(Default)] @@ -47,6 +49,18 @@ impl DirOpts { pub enum MappingHandle { Mount(UnmountDrop), + Link(LinkDrop), + None, +} + +pub struct LinkDrop { + path: PathBuf, +} + +impl Drop for LinkDrop { + fn drop(&mut self) { + std::fs::remove_file(&self.path).unwrap(); + } } impl Mapping { @@ -62,11 +76,21 @@ impl Mapping { Self::Special(src.into(), dst.into(), opt) } + fn link, P2: Into>(src: P1, dst: P2) -> Self { + Self::Link(src.into(), dst.into()) + } + + fn copy, P2: Into>(src: P1, dst: P2) -> Self { + Self::Copy(src.into(), dst.into()) + } + pub async fn create_mapping(&self, root_path: &Path) -> Result { match &self { Mapping::Device(d) => self.map_dev(d, &root_path.join(d)).await, Mapping::Dir(d, opt) => self.map_dir(d, &root_path.join(d), opt).await, Mapping::Special(src, dst, opt) => self.map_dir(src, &root_path.join(dst), opt).await, + Mapping::Link(src, dst) => self.map_link(src, &root_path.join(dst)).await, + Mapping::Copy(src, dst) => self.copy_file(src, &root_path.join(dst)).await, } } @@ -112,6 +136,32 @@ impl Mapping { Ok(MappingHandle::Mount(mount)) } + + async fn map_link(&self, src: &Path, dst: &Path) -> Result { + if dst.exists() && dst.is_symlink() { + fs::remove_file(dst).await.map_err(ChrootError::Unlink)?; + } + fs::symlink(src, dst) + .await + .map_err(|e| ChrootError::Link(dst.to_owned(), e))?; + Ok(MappingHandle::Link(LinkDrop { + path: dst.to_owned(), + })) + } + + async fn copy_file(&self, src: &Path, dst: &Path) -> Result { + if dst.exists() && dst.is_file() { + fs::remove_file(dst) + .await + .map_err(|e| ChrootError::Copy(dst.to_owned(), e))?; + } + + fs::copy(src, dst) + .await + .map_err(|e| ChrootError::Copy(dst.to_owned(), e))?; + + Ok(MappingHandle::None) + } } pub fn default_mappings() -> Vec { @@ -162,6 +212,11 @@ pub fn default_mappings() -> Vec { Mapping::dev("/dev/tty"), Mapping::dev("/dev/urandom"), Mapping::dev("/dev/zero"), + Mapping::link("/proc/self/fd", "dev/fd"), + Mapping::link("/proc/self/fd/0", "dev/stdin"), + Mapping::link("/proc/self/fd/1", "dev/stdout"), + Mapping::link("/proc/self/fd/2", "dev/stderr"), + Mapping::copy("/etc/resolv.conf", "etc/resolv.conf"), Mapping::dir( "/run", DirOpts::default().fs_type("tmpfs").flags(NOSUID | NODEV),