Skip to content

Commit

Permalink
Add SystemExt::distribution_id()
Browse files Browse the repository at this point in the history
SystemExt::name() returns human-readable distribution name,
but there is no machine-readable alternative.

SystemExt::distribution_id() returns os-release.ID, or
std::env::consts::OS if os-release.ID is unavailable.
Fallback behaviour is consistent with the os-release.ID
specification on Linux.

See also
- https://www.freedesktop.org/software/systemd/man/os-release.html#ID=
- https://doc.rust-lang.org/std/env/consts/constant.OS.html

Closes #843.
  • Loading branch information
legeana committed Sep 25, 2022
1 parent 447d464 commit 41739a4
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/apple/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,10 @@ impl SystemExt for System {
}
}
}

fn distribution_id(&self) -> String {
std::env::consts::OS.to_owned()
}
}

impl Default for System {
Expand Down
4 changes: 4 additions & 0 deletions src/freebsd/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,10 @@ impl SystemExt for System {
fn os_version(&self) -> Option<String> {
self.system_info.get_os_release()
}

fn distribution_id(&self) -> String {
std::env::consts::OS.to_owned()
}
}

impl Default for System {
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ mod test {
.long_os_version()
.expect("Failed to get long OS version")
.is_empty());

assert!(!s.distribution_id().is_empty());
}
}

Expand Down
36 changes: 36 additions & 0 deletions src/linux/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,21 @@ impl SystemExt for System {
fn os_version(&self) -> Option<String> {
get_system_info_android(InfoType::OsVersion)
}

#[cfg(not(target_os = "android"))]
fn distribution_id(&self) -> String {
get_system_info_linux(
InfoType::DistributionID,
Path::new("/etc/os-release"),
Path::new(""),
)
.unwrap_or_else(|| std::env::consts::OS.to_owned())
}

#[cfg(target_os = "android")]
fn distribution_id(&self) -> String {
std::env::consts::OS.to_owned()
}
}

impl Default for System {
Expand All @@ -722,6 +737,9 @@ enum InfoType {
/// - Linux: The distributions name
Name,
OsVersion,
/// Machine-parseable ID of a distribution, see
/// https://www.freedesktop.org/software/systemd/man/os-release.html#ID=
DistributionID,
}

#[cfg(not(target_os = "android"))]
Expand All @@ -732,6 +750,7 @@ fn get_system_info_linux(info: InfoType, path: &Path, fallback_path: &Path) -> O
let info_str = match info {
InfoType::Name => "NAME=",
InfoType::OsVersion => "VERSION_ID=",
InfoType::DistributionID => "ID=",
};

for line in reader.lines().flatten() {
Expand All @@ -750,6 +769,10 @@ fn get_system_info_linux(info: InfoType, path: &Path, fallback_path: &Path) -> O
let info_str = match info {
InfoType::OsVersion => "DISTRIB_RELEASE=",
InfoType::Name => "DISTRIB_ID=",
InfoType::DistributionID => {
// lsb-release is inconsistent with os-release and unsupported.
return None;
}
};
for line in reader.lines().flatten() {
if let Some(stripped) = line.strip_prefix(info_str) {
Expand All @@ -765,6 +788,10 @@ fn get_system_info_android(info: InfoType) -> Option<String> {
let name: &'static [u8] = match info {
InfoType::Name => b"ro.product.model\0",
InfoType::OsVersion => b"ro.build.version.release\0",
InfoType::DistributionID => {
// Not supported.
return None;
}
};

let mut value_buffer = vec![0u8; libc::PROP_VALUE_MAX as usize];
Expand Down Expand Up @@ -798,6 +825,7 @@ mod test {
fn lsb_release_fallback_android() {
assert!(get_system_info_android(InfoType::OsVersion).is_some());
assert!(get_system_info_android(InfoType::Name).is_some());
assert!(get_system_info_android(InfoType::DistributionID) == Some("android".to_owned()));
}

#[test]
Expand Down Expand Up @@ -844,6 +872,10 @@ DISTRIB_DESCRIPTION="Ubuntu 20.10"
get_system_info_linux(InfoType::Name, &tmp1, Path::new("")),
Some("Ubuntu".to_owned())
);
assert_eq!(
get_system_info_linux(InfoType::DistributionID, &tmp1, Path::new("")),
Some("ubuntu".to_owned())
);

// Check for the "fallback" path: "/etc/lsb-release"
assert_eq!(
Expand All @@ -854,5 +886,9 @@ DISTRIB_DESCRIPTION="Ubuntu 20.10"
get_system_info_linux(InfoType::Name, Path::new(""), &tmp2),
Some("Ubuntu".to_owned())
);
assert_eq!(
get_system_info_linux(InfoType::DistributionID, Path::new(""), &tmp2),
None
);
}
}
16 changes: 16 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,22 @@ pub trait SystemExt: Sized + Debug + Default + Send + Sync {
/// ```
fn long_os_version(&self) -> Option<String>;

/// Returns the distribution id as defined by os-release,
/// or OS-name if unavailable.
/// See also
/// - https://www.freedesktop.org/software/systemd/man/os-release.html#ID=
/// - https://doc.rust-lang.org/std/env/consts/constant.OS.html
///
/// **Important**: this information is computed every time this function is called.
///
/// ```no_run
/// use sysinfo::{System, SystemExt};
///
/// let s = System::new();
/// println!("Distribution ID: {:?}", s.distribution_id());
/// ```
fn distribution_id(&self) -> String;

/// Returns the system hostname based off DNS
///
/// **Important**: this information is computed every time this function is called.
Expand Down
4 changes: 4 additions & 0 deletions src/windows/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,10 @@ impl SystemExt for System {
};
Some(format!("{} ({})", major, build_number))
}

fn distribution_id(&self) -> String {
std::env::consts::OS.to_owned()
}
}

impl Default for System {
Expand Down

0 comments on commit 41739a4

Please sign in to comment.