diff --git a/src/lib/lib.rs b/src/lib/lib.rs index 6418c82..0eaa0e0 100644 --- a/src/lib/lib.rs +++ b/src/lib/lib.rs @@ -989,6 +989,11 @@ pub fn receive_package( let tar = ruzstd::decoding::StreamingDecoder::new(&mut reader).unwrap(); let mut archive = tar::Archive::new(tar); + std::fs::remove_dir_all(&dir)?; + std::fs::create_dir(&dir)?; + archive.set_overwrite(true); + archive.set_preserve_ownerships(false); + archive.set_preserve_mtime(true); archive.unpack(&dir)?; let mut packages = std::fs::OpenOptions::new() @@ -1081,32 +1086,56 @@ pub fn install_package( #[derive(Clone)] struct VisitDir<'a> { /// Fuck me. - f: &'a dyn Fn(std::io::Result, VisitDir) -> std::io::Result<()> + f: &'a dyn Fn(std::io::Result, VisitDir) -> std::io::Result<()>, } let diritem = VisitDir { - f: &|entry: std::io::Result, visit_dir: VisitDir| -> std::io::Result<()> { + f: &|entry: std::io::Result, + visit_dir: VisitDir| + -> std::io::Result<()> { let entry = entry?; - + + let entry_path = PathBuf::from( + entry + .path() + .to_string_lossy() + .strip_prefix(path.to_string_lossy().as_str()) + .unwrap_or(&entry.path().to_string_lossy()) + .strip_prefix("/") + .unwrap_or(&entry.path().to_string_lossy()), + ); + + println!("{}", entry_path.clone().to_string_lossy()); + if entry.file_name() == *".BUILDINFO" || entry.file_name() == *".MTREE" || entry.file_name() == *".PKGINFO" { return Ok(()); } - + if entry.file_name() == *".INSTALL" { + std::fs::copy(path.join(&entry_path), out.join(&entry_path))?; + return Ok(()); + } + if entry.file_type()?.is_dir() { - std::fs::create_dir_all(out.join(entry.path()))?; - for entry in std::fs::read_dir(path.join(entry.path()))? { + if !std::fs::exists(out.join(&entry_path))? { + std::fs::create_dir_all(out.join(&entry_path))?; + } + for entry in std::fs::read_dir(path.join(&entry_path))? { (visit_dir.clone().f)(entry, visit_dir.clone())?; } } else { - std::fs::create_dir_all(out.join(entry.path().parent().unwrap()))?; - std::fs::remove_file(out.join(entry.path()))?; - std::os::unix::fs::symlink(path.join(entry.path()), out.join(entry.path()))?; + if !std::fs::exists(out.join(entry_path.parent().unwrap()))? { + std::fs::create_dir_all(out.join(entry_path.parent().unwrap()))?; + } + if std::fs::exists(out.join(&entry_path))? { + std::fs::remove_file(&entry_path)?; + } + std::os::unix::fs::symlink(path.join(&entry_path), out.join(&entry_path))?; } Ok(()) - } + }, }; for entry in std::fs::read_dir(&path)? { @@ -1114,11 +1143,17 @@ pub fn install_package( } if std::fs::exists(out.join(".INSTALL"))? { - std::os::unix::fs::chroot(&out)?; + if users::get_effective_uid() == 0 { + std::os::unix::fs::chroot(&out)?; + } else { + println!("[WARN] .INSTALL script for package {} is being run without a chroot.", path.file_name().unwrap().to_string_lossy()); + println!("[WARN] The script may give permission errors or ask for authentication."); + println!(" [TIP] To run in a chroot, run the program as root."); + } if !std::process::Command::new("/usr/bin/bash") .arg("-c") - .arg("source /.INSTALL && post_install && post_upgrade") + .arg("source ./.INSTALL && post_install && post_upgrade") .current_dir(&out) .spawn()? .wait()? @@ -1130,7 +1165,9 @@ pub fn install_package( ); } - std::os::unix::fs::chroot(".")?; + if users::get_effective_uid() == 0 { + std::os::unix::fs::chroot(".")?; + } std::fs::remove_file(out.join(".INSTALL"))?; } @@ -1155,10 +1192,7 @@ pub fn install_package( /// for the current user if not. If [std::fs::create_dir_all] returns an error, it will be /// propagated. pub fn create_directories() -> Result<(), std::io::Error> { - if users::get_effective_uid() == 0 - || get_current_user() == "pacwoman" - || get_current_user() == "arthur" - { + if users::get_effective_uid() == 0 || get_current_user() == "pacwoman" { store_directory(true)?; config_directory(true)?; index_directory()?; diff --git a/src/main.rs b/src/main.rs index 5d19af1..fb6cf14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ fn main() -> std::io::Result<()> { println!("found package"); pacwoman::install_package(pacwoman::Mirror::new(url::Url::parse( "https://geo.mirror.pkgbuild.com/$repo/os/$arch", - ).unwrap()), package.1, package.0, true)?; + ).unwrap()), package.1, package.0, false)?; } Ok(())