Fix missing file link and resolv.conf in chroot

main
trivernis 2 years ago committed by Michal Stopyra
parent 735a34e2d2
commit 9dff21dc53

@ -2,9 +2,4 @@ let REQUIRES_CHROOT = true;
# Applies all system changes of `install-base` # Applies all system changes of `install-base`
def main [cfg] { def main [cfg] {
echo "Executing up task `install-base` with config" $cfg echo "Executing up task `install-base` with config" $cfg
ls /etc
cat /etc/mtab
pacman -S --noconfirm neofetch
neofetch
exit 1
} }

@ -105,6 +105,9 @@ pub enum ChrootError {
#[error("Failed to remove symlink in chroot: {0}")] #[error("Failed to remove symlink in chroot: {0}")]
Unlink(io::Error), Unlink(io::Error),
#[error("Failed to copy file {0} to chroot: {1}")]
Copy(PathBuf, io::Error),
#[error("Failed to change process working directory: {0}")] #[error("Failed to change process working directory: {0}")]
ChDir(io::Error), ChDir(io::Error),
} }

@ -9,6 +9,8 @@ pub enum Mapping {
Device(PathBuf), Device(PathBuf),
Dir(PathBuf, DirOpts), Dir(PathBuf, DirOpts),
Special(PathBuf, PathBuf, DirOpts), Special(PathBuf, PathBuf, DirOpts),
Link(PathBuf, PathBuf),
Copy(PathBuf, PathBuf),
} }
#[derive(Default)] #[derive(Default)]
@ -47,6 +49,18 @@ impl DirOpts {
pub enum MappingHandle { pub enum MappingHandle {
Mount(UnmountDrop<Mount>), Mount(UnmountDrop<Mount>),
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 { impl Mapping {
@ -62,11 +76,21 @@ impl Mapping {
Self::Special(src.into(), dst.into(), opt) Self::Special(src.into(), dst.into(), opt)
} }
fn link<P1: Into<PathBuf>, P2: Into<PathBuf>>(src: P1, dst: P2) -> Self {
Self::Link(src.into(), dst.into())
}
fn copy<P1: Into<PathBuf>, P2: Into<PathBuf>>(src: P1, dst: P2) -> Self {
Self::Copy(src.into(), dst.into())
}
pub async fn create_mapping(&self, root_path: &Path) -> Result<MappingHandle, ChrootError> { pub async fn create_mapping(&self, root_path: &Path) -> Result<MappingHandle, ChrootError> {
match &self { match &self {
Mapping::Device(d) => self.map_dev(d, &root_path.join(d)).await, 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::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::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)) Ok(MappingHandle::Mount(mount))
} }
async fn map_link(&self, src: &Path, dst: &Path) -> Result<MappingHandle, ChrootError> {
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<MappingHandle, ChrootError> {
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<Mapping> { pub fn default_mappings() -> Vec<Mapping> {
@ -162,6 +212,11 @@ pub fn default_mappings() -> Vec<Mapping> {
Mapping::dev("/dev/tty"), Mapping::dev("/dev/tty"),
Mapping::dev("/dev/urandom"), Mapping::dev("/dev/urandom"),
Mapping::dev("/dev/zero"), 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( Mapping::dir(
"/run", "/run",
DirOpts::default().fs_type("tmpfs").flags(NOSUID | NODEV), DirOpts::default().fs_type("tmpfs").flags(NOSUID | NODEV),

Loading…
Cancel
Save