Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/fetch_ld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
22 changes: 18 additions & 4 deletions src/libc_deb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = std::result::Result<T, Error>;

Expand Down Expand Up @@ -101,20 +105,30 @@ fn request_url(url: &str) -> Result<reqwest::blocking::Response> {
/// 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<reqwest::blocking::Response> {
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<reqwest::blocking::Response> {
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<P: AsRef<Path>>(
pub fn write_pkg_file<P: AsRef<Path>>(
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
Expand Down
31 changes: 21 additions & 10 deletions src/libc_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -28,6 +34,9 @@ pub struct LibcVersion {

/// Architecture of libc
pub arch: CpuArch,

/// Distribution of libc
pub distro: Distro,
}

impl fmt::Display for LibcVersion {
Expand All @@ -54,32 +63,34 @@ pub enum Error {
}

pub type Result<T> = std::result::Result<T, Error>;
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<Self> {
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<String> {
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..];
Expand All @@ -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))
}
}
2 changes: 1 addition & 1 deletion src/unstrip_libc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down