diff --git a/src/fetch_ld.rs b/src/fetch_ld.rs index c5199c4..3b58cb9 100644 --- a/src/fetch_ld.rs +++ b/src/fetch_ld.rs @@ -36,6 +36,7 @@ pub fn fetch_ld(ver: &LibcVersion) -> Result { }; let out_name = format!("ld-{}.so", ver.string_short); - libc_deb::write_ubuntu_pkg_file(&deb_file_name, &[&ld_name], out_name).context(DebSnafu)?; + libc_deb::write_pkg_file(&deb_file_name, &[&ld_name], out_name, ver.distro) + .context(DebSnafu)?; Ok(()) } diff --git a/src/libc_deb.rs b/src/libc_deb.rs index fcb59ad..1b846b7 100644 --- a/src/libc_deb.rs +++ b/src/libc_deb.rs @@ -13,8 +13,12 @@ use snafu::OptionExt; use snafu::ResultExt; use snafu::Snafu; +use crate::libc_version::Distro; + /// URL for Ubuntu glibc packages -pub static PKG_URL: &str = "https://launchpad.net/ubuntu/+archive/primary/+files/"; +pub static UBUNTU_PKG_URL: &str = "https://launchpad.net/ubuntu/+archive/primary/+files/"; +/// URL for Debian glibc packages +pub static DEBIAN_PKG_URL: &str = "https://deb.debian.org/debian/pool/main/g/glibc/"; pub type Result = std::result::Result; @@ -101,20 +105,30 @@ fn request_url(url: &str) -> Result { /// Try to get a glibc deb package with a given filename, checking both current /// and archive Ubuntu mirrors fn request_ubuntu_pkg(deb_file_name: &str) -> Result { - let url = format!("{}/{}", PKG_URL, deb_file_name); + let url = format!("{}/{}", UBUNTU_PKG_URL, deb_file_name); + request_url(&url) +} + +/// Try to get a glibc deb package with a given filename, checking current Debian mirrors +fn request_debian_pkg(deb_file_name: &str) -> Result { + let url = format!("{}/{}", DEBIAN_PKG_URL, deb_file_name); request_url(&url) } /// Download the glibc deb package with a given name, find a file inside it, and /// extract the file. -pub fn write_ubuntu_pkg_file>( +pub fn write_pkg_file>( deb_file_name: &str, file_names: &[&str], out_path: P, + distro: Distro, ) -> Result<()> { let out_path = out_path.as_ref(); - let deb_bytes = request_ubuntu_pkg(deb_file_name)?; + let deb_bytes = match distro { + Distro::Ubuntu => request_ubuntu_pkg(deb_file_name)?, + Distro::Debian => request_debian_pkg(deb_file_name)?, + }; let mut deb = ar::Archive::new(deb_bytes); // Try to find data.tar in package diff --git a/src/libc_version.rs b/src/libc_version.rs index fc4cbf9..4ba8b17 100644 --- a/src/libc_version.rs +++ b/src/libc_version.rs @@ -14,6 +14,12 @@ use snafu::ResultExt; use snafu::Snafu; use twoway::find_bytes; +#[derive(Copy, Clone)] +pub enum Distro { + Ubuntu, + Debian, +} + /// Libc version information pub struct LibcVersion { /// Long string representation of a libc version @@ -28,6 +34,9 @@ pub struct LibcVersion { /// Architecture of libc pub arch: CpuArch, + + /// Distribution of libc + pub distro: Distro, } impl fmt::Display for LibcVersion { @@ -54,32 +63,34 @@ pub enum Error { } pub type Result = std::result::Result; +const IDENTIFIER: [(&[u8], Distro); 3] = [ + (b"GNU C Library (Ubuntu GLIBC ", Distro::Ubuntu), + (b"GNU C Library (Ubuntu EGLIBC ", Distro::Ubuntu), + (b"GNU C Library (Debian GLIBC ", Distro::Debian), +]; impl LibcVersion { /// Detect the version of a libc pub fn detect(libc: &Path) -> Result { let bytes = fs::read(libc).context(ReadSnafu)?; - let string = Self::version_string_from_bytes(&bytes)?; + let (string, distro) = Self::version_str_distro_from_bytes(&bytes)?; let string_short = string.split('-').next().context(NotFoundSnafu)?.to_string(); Ok(Self { string, string_short, arch: CpuArch::from_elf_bytes(libc, &bytes).context(ArchSnafu)?, + distro, }) } /// Extract the long version string from the bytes of a libc - fn version_string_from_bytes(libc: &[u8]) -> Result { - let split: [&[u8]; 2] = [ - b"GNU C Library (Ubuntu GLIBC ", - b"GNU C Library (Ubuntu EGLIBC ", - ]; - let pos = split + fn version_str_distro_from_bytes(libc: &[u8]) -> Result<(String, Distro)> { + let (pos, distro) = IDENTIFIER .iter() - .find_map(|cut| { + .find_map(|(cut, distro)| { let pos = find_bytes(libc, cut); - Some(pos? + cut.len()) + Some((pos? + cut.len(), distro)) }) .context(NotFoundSnafu)?; let ver_str = &libc[pos..]; @@ -89,6 +100,6 @@ impl LibcVersion { .context(NotFoundSnafu)?; let ver_str = &ver_str[..pos]; let ver_str = std::str::from_utf8(ver_str).context(Utf8Snafu)?.to_string(); - Ok(ver_str) + Ok((ver_str, *distro)) } } diff --git a/src/unstrip_libc.rs b/src/unstrip_libc.rs index 18900e7..b10f7e5 100644 --- a/src/unstrip_libc.rs +++ b/src/unstrip_libc.rs @@ -64,7 +64,7 @@ fn do_unstrip_libc(libc: &Path, ver: &LibcVersion) -> Result { }; let names = [name1.as_str(), name2.as_str()]; - libc_deb::write_ubuntu_pkg_file(&deb_file_name, names.as_slice(), &sym_path) + libc_deb::write_pkg_file(&deb_file_name, names.as_slice(), &sym_path, ver.distro) .context(DebSnafu)?; let out = Command::new("eu-unstrip")