summaryrefslogtreecommitdiffstats
path: root/vendor/os_info/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/os_info/src
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/os_info/src')
-rw-r--r--vendor/os_info/src/android/mod.rs23
-rw-r--r--vendor/os_info/src/bitness.rs124
-rw-r--r--vendor/os_info/src/dragonfly/mod.rs35
-rw-r--r--vendor/os_info/src/emscripten/mod.rs24
-rw-r--r--vendor/os_info/src/freebsd/mod.rs60
-rw-r--r--vendor/os_info/src/illumos/mod.rs67
-rw-r--r--vendor/os_info/src/info.rs311
-rw-r--r--vendor/os_info/src/lib.rs111
-rw-r--r--vendor/os_info/src/linux/file_release.rs493
-rw-r--r--vendor/os_info/src/linux/lsb_release.rs482
-rw-r--r--vendor/os_info/src/linux/mod.rs56
-rw-r--r--vendor/os_info/src/linux/tests/Alpine/etc/alpine-release1
-rw-r--r--vendor/os_info/src/linux/tests/Alpine_3_12/etc/os-release6
-rw-r--r--vendor/os_info/src/linux/tests/Amazon_1/etc/os-release9
-rw-r--r--vendor/os_info/src/linux/tests/Amazon_2/etc/os-release9
-rw-r--r--vendor/os_info/src/linux/tests/CentOS/etc/centos-release1
-rw-r--r--vendor/os_info/src/linux/tests/CentOS_7/etc/os-release15
-rw-r--r--vendor/os_info/src/linux/tests/CentOS_Stream/etc/os-release13
-rw-r--r--vendor/os_info/src/linux/tests/CentOS_Unknown/etc/centos-release1
-rw-r--r--vendor/os_info/src/linux/tests/Fedora/etc/fedora-release1
-rw-r--r--vendor/os_info/src/linux/tests/Fedora_32/etc/os-release21
-rw-r--r--vendor/os_info/src/linux/tests/Fedora_35/etc/os-release21
-rw-r--r--vendor/os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release1
-rw-r--r--vendor/os_info/src/linux/tests/Mariner/etc/mariner-release2
-rw-r--r--vendor/os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release1
-rw-r--r--vendor/os_info/src/linux/tests/Mint/etc/os-release12
-rw-r--r--vendor/os_info/src/linux/tests/NixOS/etc/os-release11
-rw-r--r--vendor/os_info/src/linux/tests/OracleLinux/etc/os-release18
-rw-r--r--vendor/os_info/src/linux/tests/OracleLinux/etc/redhat-release1
-rw-r--r--vendor/os_info/src/linux/tests/RedHatEnterprise/etc/redhat-release1
-rw-r--r--vendor/os_info/src/linux/tests/RedHatEnterprise_7/etc/os-release17
-rw-r--r--vendor/os_info/src/linux/tests/RedHatEnterprise_8/etc/os-release16
-rw-r--r--vendor/os_info/src/linux/tests/RedHatEnterprise_Unknown/etc/redhat-release0
-rw-r--r--vendor/os_info/src/linux/tests/SUSE_12/etc/os-release7
-rw-r--r--vendor/os_info/src/linux/tests/SUSE_15/etc/os-release8
-rw-r--r--vendor/os_info/src/linux/tests/Ubuntu/etc/os-release12
-rw-r--r--vendor/os_info/src/linux/tests/none_invalid_os_release/etc/os-release2
-rw-r--r--vendor/os_info/src/macos/mod.rs106
-rw-r--r--vendor/os_info/src/matcher.rs148
-rw-r--r--vendor/os_info/src/netbsd/mod.rs35
-rw-r--r--vendor/os_info/src/openbsd/mod.rs35
-rw-r--r--vendor/os_info/src/os_type.rs162
-rw-r--r--vendor/os_info/src/redox/mod.rs54
-rw-r--r--vendor/os_info/src/uname.rs32
-rw-r--r--vendor/os_info/src/unknown/mod.rs20
-rw-r--r--vendor/os_info/src/version.rs150
-rw-r--r--vendor/os_info/src/windows/mod.rs26
-rw-r--r--vendor/os_info/src/windows/winapi.rs371
48 files changed, 3132 insertions, 0 deletions
diff --git a/vendor/os_info/src/android/mod.rs b/vendor/os_info/src/android/mod.rs
new file mode 100644
index 000000000..51c99ba88
--- /dev/null
+++ b/vendor/os_info/src/android/mod.rs
@@ -0,0 +1,23 @@
+use log::trace;
+
+use crate::{Bitness, Info, Type};
+
+pub fn current_platform() -> Info {
+ trace!("android::current_platform is called");
+
+ let info = Info::with_type(Type::Android);
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::Android, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/bitness.rs b/vendor/os_info/src/bitness.rs
new file mode 100644
index 000000000..dba7e1c83
--- /dev/null
+++ b/vendor/os_info/src/bitness.rs
@@ -0,0 +1,124 @@
+// spell-checker:ignore getconf
+
+use std::fmt::{self, Display, Formatter};
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
+use std::process::{Command, Output};
+
+/// Operating system architecture in terms of how many bits compose the basic values it can deal with.
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[non_exhaustive]
+pub enum Bitness {
+ /// Unknown bitness (unable to determine).
+ Unknown,
+ /// 32-bit.
+ X32,
+ /// 64-bit.
+ X64,
+}
+
+impl Display for Bitness {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match *self {
+ Bitness::Unknown => write!(f, "unknown bitness"),
+ Bitness::X32 => write!(f, "32-bit"),
+ Bitness::X64 => write!(f, "64-bit"),
+ }
+ }
+}
+
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "macos",
+))]
+pub fn get() -> Bitness {
+ match &Command::new("getconf").arg("LONG_BIT").output() {
+ Ok(Output { stdout, .. }) if stdout == b"32\n" => Bitness::X32,
+ Ok(Output { stdout, .. }) if stdout == b"64\n" => Bitness::X64,
+ _ => Bitness::Unknown,
+ }
+}
+
+#[cfg(target_os = "netbsd")]
+pub fn get() -> Bitness {
+ match &Command::new("sysctl")
+ .arg("-n")
+ .arg("hw.machine_arch")
+ .output()
+ {
+ Ok(Output { stdout, .. }) if stdout == b"amd64\n" => Bitness::X64,
+ Ok(Output { stdout, .. }) if stdout == b"x86_64\n" => Bitness::X64,
+ Ok(Output { stdout, .. }) if stdout == b"i386\n" => Bitness::X32,
+ Ok(Output { stdout, .. }) if stdout == b"aarch64\n" => Bitness::X64,
+ Ok(Output { stdout, .. }) if stdout == b"earmv7hf\n" => Bitness::X32,
+ Ok(Output { stdout, .. }) if stdout == b"sparc64\n" => Bitness::X64,
+ _ => Bitness::Unknown,
+ }
+}
+
+#[cfg(target_os = "openbsd")]
+pub fn get() -> Bitness {
+ match &Command::new("sysctl").arg("-n").arg("hw.machine").output() {
+ Ok(Output { stdout, .. }) if stdout == b"amd64\n" => Bitness::X64,
+ Ok(Output { stdout, .. }) if stdout == b"x86_64\n" => Bitness::X64,
+ Ok(Output { stdout, .. }) if stdout == b"i386\n" => Bitness::X32,
+ Ok(Output { stdout, .. }) if stdout == b"aarch64\n" => Bitness::X64,
+ Ok(Output { stdout, .. }) if stdout == b"earmv7hf\n" => Bitness::X32,
+ Ok(Output { stdout, .. }) if stdout == b"sparc64\n" => Bitness::X64,
+ _ => Bitness::Unknown,
+ }
+}
+
+#[cfg(target_os = "illumos")]
+pub fn get() -> Bitness {
+ match &Command::new("isainfo").arg("-b").output() {
+ Ok(Output { stdout, .. }) if stdout == b"64\n" => Bitness::X64,
+ Ok(Output { stdout, .. }) if stdout == b"32\n" => Bitness::X32,
+ _ => Bitness::Unknown,
+ }
+}
+
+#[cfg(all(
+ test,
+ any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )
+))]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_ne;
+
+ #[test]
+ fn get_bitness() {
+ let b = get();
+ assert_ne!(b, Bitness::Unknown);
+ }
+
+ #[test]
+ fn display() {
+ let data = [
+ (Bitness::Unknown, "unknown bitness"),
+ (Bitness::X32, "32-bit"),
+ (Bitness::X64, "64-bit"),
+ ];
+
+ for (bitness, expected) in &data {
+ assert_eq!(&bitness.to_string(), expected);
+ }
+ }
+}
diff --git a/vendor/os_info/src/dragonfly/mod.rs b/vendor/os_info/src/dragonfly/mod.rs
new file mode 100644
index 000000000..63fe0e7c4
--- /dev/null
+++ b/vendor/os_info/src/dragonfly/mod.rs
@@ -0,0 +1,35 @@
+use std::process::Command;
+
+use log::trace;
+
+use crate::{bitness, uname::uname, Bitness, Info, Type, Version};
+
+pub fn current_platform() -> Info {
+ trace!("dragonfly::current_platform is called");
+
+ let version = uname()
+ .map(Version::from_string)
+ .unwrap_or_else(|| Version::Unknown);
+
+ let info = Info {
+ os_type: Type::DragonFly,
+ version,
+ bitness: bitness::get(),
+ ..Default::default()
+ };
+
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::DragonFly, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/emscripten/mod.rs b/vendor/os_info/src/emscripten/mod.rs
new file mode 100644
index 000000000..36be37706
--- /dev/null
+++ b/vendor/os_info/src/emscripten/mod.rs
@@ -0,0 +1,24 @@
+use log::trace;
+
+use crate::{Bitness, Info, Type};
+
+// TODO: Somehow get the real OS version?
+pub fn current_platform() -> Info {
+ trace!("emscripten::current_platform is called");
+
+ let info = Info::with_type(Type::Emscripten);
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::Emscripten, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/freebsd/mod.rs b/vendor/os_info/src/freebsd/mod.rs
new file mode 100644
index 000000000..09c8dbe88
--- /dev/null
+++ b/vendor/os_info/src/freebsd/mod.rs
@@ -0,0 +1,60 @@
+use std::process::Command;
+use std::str;
+
+use log::{error, trace};
+
+use crate::{bitness, uname::uname, Info, Type, Version};
+
+pub fn current_platform() -> Info {
+ trace!("freebsd::current_platform is called");
+
+ let version = uname()
+ .map(Version::from_string)
+ .unwrap_or_else(|| Version::Unknown);
+
+ let info = Info {
+ os_type: get_os(),
+ version,
+ bitness: bitness::get(),
+ ..Default::default()
+ };
+
+ trace!("Returning {:?}", info);
+ info
+}
+
+fn get_os() -> Type {
+ let os = Command::new("uname")
+ .arg("-s")
+ .output()
+ .expect("Failed to get OS");
+
+ match str::from_utf8(&os.stdout) {
+ Ok("FreeBSD\n") => {
+ let check_hardening = Command::new("sysctl")
+ .arg("hardening.version")
+ .output()
+ .expect("Failed to check if is hardened");
+ match str::from_utf8(&check_hardening.stderr) {
+ Ok("0\n") => Type::HardenedBSD,
+ Ok(_) => Type::FreeBSD,
+ Err(_) => Type::FreeBSD,
+ }
+ }
+ Ok("MidnightBSD\n") => Type::MidnightBSD,
+ Ok(_) => Type::Unknown,
+ Err(_) => Type::Unknown,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::FreeBSD, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/illumos/mod.rs b/vendor/os_info/src/illumos/mod.rs
new file mode 100644
index 000000000..1f23771f1
--- /dev/null
+++ b/vendor/os_info/src/illumos/mod.rs
@@ -0,0 +1,67 @@
+use std::process::Command;
+use std::str;
+
+use log::{error, trace};
+
+use crate::{bitness, uname::uname, Info, Type, Version};
+
+pub fn current_platform() -> Info {
+ trace!("illumos::current_platform is called");
+
+ let version = get_version()
+ .map(Version::from_string)
+ .unwrap_or_else(|| Version::Unknown);
+
+ let info = Info {
+ os_type: get_os(),
+ version,
+ bitness: bitness::get(),
+ ..Default::default()
+ };
+
+ trace!("Returning {:?}", info);
+ info
+}
+
+fn get_version() -> Option<String> {
+ Command::new("uname")
+ .arg("-v")
+ .output()
+ .map_err(|e| {
+ error!("Failed to invoke 'uname': {:?}", e);
+ })
+ .ok()
+ .and_then(|out| {
+ if out.status.success() {
+ Some(String::from_utf8_lossy(&out.stdout).trim_end().to_owned())
+ } else {
+ log::error!("'uname' invocation error: {:?}", out);
+ None
+ }
+ })
+}
+
+fn get_os() -> Type {
+ let os = Command::new("uname")
+ .arg("-o")
+ .output()
+ .expect("Failed to get OS");
+
+ match str::from_utf8(&os.stdout) {
+ Ok("illumos\n") => Type::Illumos,
+ Ok(_) => Type::Unknown,
+ Err(_) => Type::Unknown,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::Illumos, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/info.rs b/vendor/os_info/src/info.rs
new file mode 100644
index 000000000..85b699330
--- /dev/null
+++ b/vendor/os_info/src/info.rs
@@ -0,0 +1,311 @@
+// spell-checker:ignore itertools, iproduct, bitnesses
+
+use std::fmt::{self, Display, Formatter};
+
+use super::{Bitness, Type, Version};
+
+/// Holds information about operating system (type, version, etc.).
+///
+/// The best way to get string representation of the operation system information is to use its
+/// `Display` implementation.
+///
+/// # Examples
+///
+/// ```
+/// use os_info;
+///
+/// let info = os_info::get();
+/// println!("OS information: {}", info);
+/// ```
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub struct Info {
+ /// Operating system type. See `Type` for details.
+ pub(crate) os_type: Type,
+ /// Operating system version. See `Version` for details.
+ pub(crate) version: Version,
+ /// Operating system edition.
+ pub(crate) edition: Option<String>,
+ /// Operating system edition.
+ pub(crate) codename: Option<String>,
+ /// Operating system architecture in terms of how many bits compose the basic values it can deal
+ /// with. See `Bitness` for details.
+ pub(crate) bitness: Bitness,
+}
+
+impl Info {
+ /// Constructs a new `Info` instance with unknown type, version and bitness.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::{Info, Type, Version, Bitness};
+ ///
+ /// let info = Info::unknown();
+ /// assert_eq!(Type::Unknown, info.os_type());
+ /// assert_eq!(&Version::Unknown, info.version());
+ /// assert_eq!(None, info.edition());
+ /// assert_eq!(None, info.codename());
+ /// assert_eq!(Bitness::Unknown, info.bitness());
+ /// ```
+ pub fn unknown() -> Self {
+ Self {
+ os_type: Type::Unknown,
+ version: Version::Unknown,
+ edition: None,
+ codename: None,
+ bitness: Bitness::Unknown,
+ }
+ }
+
+ /// Constructs a new `Info` instance with the specified operating system type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::{Info, Type, Version, Bitness};
+ ///
+ /// let os_type = Type::Linux;
+ /// let info = Info::with_type(os_type);
+ /// assert_eq!(os_type, info.os_type());
+ /// assert_eq!(&Version::Unknown, info.version());
+ /// assert_eq!(None, info.edition());
+ /// assert_eq!(None, info.codename());
+ /// assert_eq!(Bitness::Unknown, info.bitness());
+ /// ```
+ pub fn with_type(os_type: Type) -> Self {
+ Self {
+ os_type,
+ ..Default::default()
+ }
+ }
+
+ /// Returns operating system type. See `Type` for details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::{Info, Type};
+ ///
+ /// let info = Info::unknown();
+ /// assert_eq!(Type::Unknown, info.os_type());
+ /// ```
+ pub fn os_type(&self) -> Type {
+ self.os_type
+ }
+
+ /// Returns operating system version. See `Version` for details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::{Info, Version};
+ ///
+ /// let info = Info::unknown();
+ /// assert_eq!(&Version::Unknown, info.version());
+ /// ```
+ pub fn version(&self) -> &Version {
+ &self.version
+ }
+
+ /// Returns optional operation system edition.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::Info;
+ ///
+ /// let info = Info::unknown();
+ /// assert_eq!(None, info.edition());
+ pub fn edition(&self) -> Option<&str> {
+ self.edition.as_ref().map(String::as_ref)
+ }
+
+ /// Returns optional operation system 'codename'.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::Info;
+ ///
+ /// let info = Info::unknown();
+ /// assert_eq!(None, info.codename());
+ pub fn codename(&self) -> Option<&str> {
+ self.codename.as_ref().map(String::as_ref)
+ }
+
+ /// Returns operating system bitness. See `Bitness` for details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::{Info, Bitness};
+ ///
+ /// let info = Info::unknown();
+ /// assert_eq!(Bitness::Unknown, info.bitness());
+ /// ```
+ pub fn bitness(&self) -> Bitness {
+ self.bitness
+ }
+}
+
+impl Default for Info {
+ fn default() -> Self {
+ Self::unknown()
+ }
+}
+
+impl Display for Info {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "{}", self.os_type)?;
+ if self.version != Version::Unknown {
+ write!(f, " {}", self.version)?;
+ }
+ if let Some(ref edition) = self.edition {
+ write!(f, " ({})", edition)?;
+ }
+ if let Some(ref codename) = self.codename {
+ write!(f, " ({})", codename)?;
+ }
+ write!(f, " [{}]", self.bitness)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn unknown() {
+ let info = Info::unknown();
+ assert_eq!(Type::Unknown, info.os_type());
+ assert_eq!(&Version::Unknown, info.version());
+ assert_eq!(None, info.edition());
+ assert_eq!(None, info.codename());
+ assert_eq!(Bitness::Unknown, info.bitness());
+ }
+
+ #[test]
+ fn with_type() {
+ let types = [
+ Type::Redox,
+ Type::Alpine,
+ Type::Amazon,
+ Type::Android,
+ Type::Arch,
+ Type::CentOS,
+ Type::Debian,
+ Type::Emscripten,
+ Type::EndeavourOS,
+ Type::Fedora,
+ Type::Gentoo,
+ Type::Linux,
+ Type::Macos,
+ Type::Manjaro,
+ Type::Mariner,
+ Type::NixOS,
+ Type::openSUSE,
+ Type::OracleLinux,
+ Type::Pop,
+ Type::Redhat,
+ Type::RedHatEnterprise,
+ Type::Redox,
+ Type::Solus,
+ Type::SUSE,
+ Type::Ubuntu,
+ Type::Mint,
+ Type::Unknown,
+ Type::Windows,
+ ];
+
+ for t in &types {
+ let info = Info::with_type(*t);
+ assert_eq!(t, &info.os_type());
+ }
+ }
+
+ #[test]
+ fn default() {
+ assert_eq!(Info::default(), Info::unknown());
+ }
+
+ #[test]
+ fn display() {
+ let data = [
+ // All unknown.
+ (Info::unknown(), "Unknown [unknown bitness]"),
+ // Type.
+ (
+ Info {
+ os_type: Type::Redox,
+ ..Default::default()
+ },
+ "Redox [unknown bitness]",
+ ),
+ // Type and version.
+ (
+ Info {
+ os_type: Type::Linux,
+ version: Version::Semantic(2, 3, 4),
+ ..Default::default()
+ },
+ "Linux 2.3.4 [unknown bitness]",
+ ),
+ (
+ Info {
+ os_type: Type::Arch,
+ version: Version::Rolling(None),
+ ..Default::default()
+ },
+ "Arch Linux Rolling Release [unknown bitness]",
+ ),
+ (
+ Info {
+ os_type: Type::Manjaro,
+ version: Version::Rolling(Some("2020.05.24".to_owned())),
+ ..Default::default()
+ },
+ "Manjaro Rolling Release (2020.05.24) [unknown bitness]",
+ ),
+ (
+ Info {
+ os_type: Type::Windows,
+ version: Version::Custom("Special Version".to_owned()),
+ ..Default::default()
+ },
+ "Windows Special Version [unknown bitness]",
+ ),
+ // Bitness.
+ (
+ Info {
+ bitness: Bitness::X32,
+ ..Default::default()
+ },
+ "Unknown [32-bit]",
+ ),
+ (
+ Info {
+ bitness: Bitness::X64,
+ ..Default::default()
+ },
+ "Unknown [64-bit]",
+ ),
+ // All info.
+ (
+ Info {
+ os_type: Type::Macos,
+ version: Version::Semantic(10, 2, 0),
+ edition: Some("edition".to_owned()),
+ codename: Some("codename".to_owned()),
+ bitness: Bitness::X64,
+ },
+ "Mac OS 10.2.0 (edition) (codename) [64-bit]",
+ ),
+ ];
+
+ for (info, expected) in &data {
+ assert_eq!(expected, &info.to_string());
+ }
+ }
+}
diff --git a/vendor/os_info/src/lib.rs b/vendor/os_info/src/lib.rs
new file mode 100644
index 000000000..a1a6746ec
--- /dev/null
+++ b/vendor/os_info/src/lib.rs
@@ -0,0 +1,111 @@
+//! `os_info`
+//!
+//! Provides interfaces for getting information about the current operating system, such as type,
+//! version, edition and bitness.
+
+#![deny(
+ missing_debug_implementations,
+ missing_docs,
+ unsafe_code,
+ missing_doc_code_examples
+)]
+
+#[cfg(target_os = "android")]
+#[path = "android/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "dragonfly")]
+#[path = "dragonfly/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "emscripten")]
+#[path = "emscripten/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "freebsd")]
+#[path = "freebsd/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "illumos")]
+#[path = "illumos/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "linux")]
+#[path = "linux/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "macos")]
+#[path = "macos/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "netbsd")]
+#[path = "netbsd/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "openbsd")]
+#[path = "openbsd/mod.rs"]
+mod imp;
+
+#[cfg(target_os = "redox")]
+#[path = "redox/mod.rs"]
+mod imp;
+
+#[cfg(windows)]
+#[path = "windows/mod.rs"]
+mod imp;
+
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "windows"
+)))]
+#[path = "unknown/mod.rs"]
+mod imp;
+
+mod bitness;
+mod info;
+#[cfg(not(windows))]
+mod matcher;
+mod os_type;
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
+mod uname;
+mod version;
+
+pub use crate::{bitness::Bitness, info::Info, os_type::Type, version::Version};
+
+/// Returns information about the current operating system (type, version, edition, etc.).
+///
+/// # Examples
+///
+/// ```
+/// use os_info;
+///
+/// let info = os_info::get();
+///
+/// // Print full information:
+/// println!("OS information: {}", info);
+///
+/// // Print information separately:
+/// println!("Type: {}", info.os_type());
+/// println!("Version: {}", info.version());
+/// println!("Edition: {:?}", info.edition());
+/// println!("Codename: {:?}", info.codename());
+/// println!("Bitness: {}", info.bitness());
+/// ```
+pub fn get() -> Info {
+ imp::current_platform()
+}
diff --git a/vendor/os_info/src/linux/file_release.rs b/vendor/os_info/src/linux/file_release.rs
new file mode 100644
index 000000000..119c85560
--- /dev/null
+++ b/vendor/os_info/src/linux/file_release.rs
@@ -0,0 +1,493 @@
+// spell-checker:ignore sles
+
+use std::{fmt, fs::File, io::Read, path::Path};
+
+use log::{trace, warn};
+
+use crate::{matcher::Matcher, Bitness, Info, Type, Version};
+
+pub fn get() -> Option<Info> {
+ retrieve(&DISTRIBUTIONS, "/")
+}
+
+fn retrieve(distributions: &[ReleaseInfo], root: &str) -> Option<Info> {
+ for release_info in distributions {
+ let path = Path::new(root).join(release_info.path);
+
+ if !path.exists() {
+ trace!("Path '{}' doesn't exist", release_info.path);
+ continue;
+ }
+
+ let mut file = match File::open(&path) {
+ Ok(val) => val,
+ Err(e) => {
+ warn!("Unable to open {:?} file: {:?}", &path, e);
+ continue;
+ }
+ };
+
+ let mut file_content = String::new();
+ if let Err(e) = file.read_to_string(&mut file_content) {
+ warn!("Unable to read {:?} file: {:?}", &path, e);
+ continue;
+ }
+
+ let os_type = (release_info.os_type)(&file_content);
+
+ // If os_type is indeterminate, try the next release_info
+ if os_type.is_none() {
+ continue;
+ }
+
+ let version = (release_info.version)(&file_content);
+
+ return Some(Info {
+ os_type: os_type.unwrap(),
+ version: version.unwrap_or(Version::Unknown),
+ bitness: Bitness::Unknown,
+ ..Default::default()
+ });
+ }
+
+ // Failed to determine os info
+ None
+}
+
+/// Struct containing information on how to parse distribution info from a release file.
+#[derive(Clone)]
+struct ReleaseInfo<'a> {
+ /// Relative path to the release file this struct corresponds to from root.
+ path: &'a str,
+
+ /// A closure that determines the os type from the release file contents.
+ os_type: for<'b> fn(&'b str) -> Option<Type>,
+
+ /// A closure that determines the os version from the release file contents.
+ version: for<'b> fn(&'b str) -> Option<Version>,
+}
+
+impl fmt::Debug for ReleaseInfo<'_> {
+ fn fmt<'a>(&'a self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("ReleaseInfo")
+ .field("path", &self.path)
+ .field("os_type", &(self.os_type as fn(&'a str) -> Option<Type>))
+ .field("version", &(self.version as fn(&'a str) -> Option<Version>))
+ .finish()
+ }
+}
+
+/// List of all supported distributions and the information on how to parse their version from the
+/// release file.
+static DISTRIBUTIONS: [ReleaseInfo; 6] = [
+ // Keep this first; most modern distributions have this file.
+ ReleaseInfo {
+ path: "etc/os-release",
+ os_type: |release| {
+ Matcher::KeyValue { key: "ID" }
+ .find(release)
+ .and_then(|id| match id.as_str() {
+ // os-release information collected from
+ // https://github.com/chef/os_release
+
+ //"almalinux" => Alma
+ "alpine" => Some(Type::Alpine),
+ "amzn" => Some(Type::Amazon),
+ //"antergos" => Antergos
+ //"aosc" => AOSC
+ "arch" => Some(Type::Arch),
+ //"artix" => Artix
+ "centos" => Some(Type::CentOS),
+ //"clear-linux-os" => ClearLinuxOS
+ //"clearos" => ClearOS
+ //"coreos"
+ //"cumulus-linux" => Cumulus
+ //"debian" => Debian
+ //"devuan" => Devuan
+ //"elementary" => Elementary
+ "fedora" => Some(Type::Fedora),
+ //"gentoo" => Gentoo
+ //"ios_xr" => ios_xr
+ //"kali" => Kali
+ //"mageia" => Mageia
+ //"manjaro" => Manjaro
+ "linuxmint" => Some(Type::Mint),
+ "mariner" => Some(Type::Mariner),
+ //"nexus" => Nexus
+ "nixos" => Some(Type::NixOS),
+ "ol" => Some(Type::OracleLinux),
+ "opensuse" => Some(Type::openSUSE),
+ "opensuse-leap" => Some(Type::openSUSE),
+ //"rancheros" => RancherOS
+ //"raspbian" => Raspbian
+ // note XBian also uses "raspbian"
+ "rhel" => Some(Type::RedHatEnterprise),
+ //"rocky" => Rocky
+ //"sabayon" => Sabayon
+ //"scientific" => Scientific
+ //"slackware" => Slackware
+ "sled" => Some(Type::SUSE), // SUSE desktop
+ "sles" => Some(Type::SUSE),
+ "sles_sap" => Some(Type::SUSE), // SUSE SAP
+ "ubuntu" => Some(Type::Ubuntu),
+ //"virtuozzo" => Virtuozzo
+ //"void" => Void
+ //"XCP-ng" => xcp-ng
+ //"xenenterprise" => xcp-ng
+ //"xenserver" => xcp-ng
+ _ => None,
+ })
+ },
+ version: |release| {
+ Matcher::KeyValue { key: "VERSION_ID" }
+ .find(release)
+ .map(Version::from_string)
+ },
+ },
+ // Older distributions must have their specific release file parsed.
+ ReleaseInfo {
+ path: "etc/mariner-release",
+ os_type: |_| Some(Type::Mariner),
+ version: |release| {
+ Matcher::PrefixedVersion {
+ prefix: "CBL-Mariner",
+ }
+ .find(release)
+ .map(Version::from_string)
+ },
+ },
+ ReleaseInfo {
+ path: "etc/centos-release",
+ os_type: |_| Some(Type::CentOS),
+ version: |release| {
+ Matcher::PrefixedVersion { prefix: "release" }
+ .find(release)
+ .map(Version::from_string)
+ },
+ },
+ ReleaseInfo {
+ path: "etc/fedora-release",
+ os_type: |_| Some(Type::Fedora),
+ version: |release| {
+ Matcher::PrefixedVersion { prefix: "release" }
+ .find(release)
+ .map(Version::from_string)
+ },
+ },
+ ReleaseInfo {
+ path: "etc/alpine-release",
+ os_type: |_| Some(Type::Alpine),
+ version: |release| Matcher::AllTrimmed.find(release).map(Version::from_string),
+ },
+ ReleaseInfo {
+ path: "etc/redhat-release",
+ os_type: |_| Some(Type::RedHatEnterprise),
+ version: |release| {
+ Matcher::PrefixedVersion { prefix: "release" }
+ .find(release)
+ .map(Version::from_string)
+ },
+ },
+];
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn alpine_3_12_os_release() {
+ let root = "src/linux/tests/Alpine_3_12";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Alpine);
+ assert_eq!(info.version, Version::Semantic(3, 12, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn alpine_release() {
+ let root = "src/linux/tests/Alpine";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Alpine);
+ assert_eq!(info.version, Version::Custom("A.B.C".to_owned()));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn amazon_1_os_release() {
+ let root = "src/linux/tests/Amazon_1";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Amazon);
+ assert_eq!(info.version, Version::Semantic(2018, 3, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn amazon_2_os_release() {
+ let root = "src/linux/tests/Amazon_2";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Amazon);
+ assert_eq!(info.version, Version::Semantic(2, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn centos_7_os_release() {
+ let root = "src/linux/tests/CentOS_7";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::CentOS);
+ assert_eq!(info.version, Version::Semantic(7, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn centos_stream_os_release() {
+ let root = "src/linux/tests/CentOS_Stream";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::CentOS);
+ assert_eq!(info.version, Version::Semantic(8, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn centos_release() {
+ let root = "src/linux/tests/CentOS";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::CentOS);
+ assert_eq!(info.version, Version::Custom("XX".to_owned()));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn centos_release_unknown() {
+ let root = "src/linux/tests/CentOS_Unknown";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::CentOS);
+ assert_eq!(info.version, Version::Unknown);
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn fedora_32_os_release() {
+ let root = "src/linux/tests/Fedora_32";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Fedora);
+ assert_eq!(info.version, Version::Semantic(32, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn fedora_35_os_release() {
+ let root = "src/linux/tests/Fedora_35";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Fedora);
+ assert_eq!(info.version, Version::Semantic(35, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn fedora_release() {
+ let root = "src/linux/tests/Fedora";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Fedora);
+ assert_eq!(info.version, Version::Semantic(26, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn fedora_release_unknown() {
+ let root = "src/linux/tests/Fedora_Unknown";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Fedora);
+ assert_eq!(info.version, Version::Unknown);
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn mariner_release() {
+ let root = "src/linux/tests/Mariner";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Mariner);
+ assert_eq!(info.version, Version::Semantic(2, 0, 20220210));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn mariner_release_unknown() {
+ let root = "src/linux/tests/Mariner_Unknown";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Mariner);
+ assert_eq!(info.version, Version::Unknown);
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn mint_os_release() {
+ let root = "src/linux/tests/Mint";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Mint);
+ assert_eq!(info.version, Version::Semantic(20, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn nixos_os_release() {
+ let root = "src/linux/tests/NixOS";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::NixOS);
+ assert_eq!(
+ info.version,
+ Version::Custom("21.05pre275822.916ee862e87".to_string())
+ );
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn none_invalid_os_release() {
+ let root = "src/linux/tests/none_invalid_os_release";
+
+ let info = retrieve(&DISTRIBUTIONS, root);
+ assert_eq!(info, None);
+ }
+
+ #[test]
+ fn none_no_release() {
+ let root = "src/linux/tests/none_no_release";
+
+ let info = retrieve(&DISTRIBUTIONS, root);
+ assert_eq!(info, None);
+ }
+
+ #[test]
+ fn none_no_path() {
+ let root = "src/linux/tests/none_no_path";
+
+ let info = retrieve(&DISTRIBUTIONS, root);
+ assert_eq!(info, None);
+ }
+
+ #[test]
+ fn oracle_linux_os_release() {
+ let root = "src/linux/tests/OracleLinux";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::OracleLinux);
+ assert_eq!(info.version, Version::Semantic(8, 1, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn rhel_8_os_release() {
+ let root = "src/linux/tests/RedHatEnterprise_8";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::RedHatEnterprise);
+ assert_eq!(info.version, Version::Semantic(8, 2, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn rhel_7_os_release() {
+ let root = "src/linux/tests/RedHatEnterprise_7";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::RedHatEnterprise);
+ assert_eq!(info.version, Version::Semantic(7, 9, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn redhat_release() {
+ let root = "src/linux/tests/RedHatEnterprise";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::RedHatEnterprise);
+ assert_eq!(info.version, Version::Custom("XX".to_owned()));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn redhat_release_unknown() {
+ let root = "src/linux/tests/RedHatEnterprise_Unknown";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::RedHatEnterprise);
+ assert_eq!(info.version, Version::Unknown);
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn suse_12_os_release() {
+ let root = "src/linux/tests/SUSE_12";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::SUSE);
+ assert_eq!(info.version, Version::Semantic(12, 5, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn suse_15_os_release() {
+ let root = "src/linux/tests/SUSE_15";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::SUSE);
+ assert_eq!(info.version, Version::Semantic(15, 2, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn ubuntu_os_release() {
+ let root = "src/linux/tests/Ubuntu";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Ubuntu);
+ assert_eq!(info.version, Version::Semantic(18, 10, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn release_info_debug() {
+ dbg!("{:?}", &DISTRIBUTIONS[0]);
+ }
+}
diff --git a/vendor/os_info/src/linux/lsb_release.rs b/vendor/os_info/src/linux/lsb_release.rs
new file mode 100644
index 000000000..58a96ae2a
--- /dev/null
+++ b/vendor/os_info/src/linux/lsb_release.rs
@@ -0,0 +1,482 @@
+// spell-checker:ignore codename, noarch, rhel, ootpa, maipo
+
+use std::process::Command;
+
+use log::{debug, trace};
+
+use crate::{matcher::Matcher, Info, Type, Version};
+
+pub fn get() -> Option<Info> {
+ let release = retrieve()?;
+
+ let version = match release.version.as_deref() {
+ Some("rolling") => Version::Rolling(None),
+ Some(v) => Version::Custom(v.to_owned()),
+ None => Version::Unknown,
+ };
+
+ let os_type = match release.distribution.as_ref().map(String::as_ref) {
+ Some("Amazon") | Some("AmazonAMI") => Type::Amazon,
+ Some("Arch") => Type::Arch,
+ Some("CentOS") => Type::CentOS,
+ Some("Debian") => Type::Debian,
+ Some("EndeavourOS") => Type::EndeavourOS,
+ Some("Fedora") | Some("Fedora Linux") => Type::Fedora,
+ Some("Garuda") => Type::Garuda,
+ Some("Gentoo") => Type::Gentoo,
+ Some("Linuxmint") => Type::Mint,
+ Some("ManjaroLinux") => Type::Manjaro,
+ Some("Mariner") => Type::Mariner,
+ Some("NixOS") => Type::NixOS,
+ Some("openSUSE") => Type::openSUSE,
+ Some("OracleServer") => Type::OracleLinux,
+ Some("Pop") => Type::Pop,
+ Some("Raspbian") => Type::Raspbian,
+ Some("RedHatEnterprise") | Some("RedHatEnterpriseServer") => Type::RedHatEnterprise,
+ Some("Solus") => Type::Solus,
+ Some("SUSE") => Type::SUSE,
+ Some("Ubuntu") => Type::Ubuntu,
+ _ => Type::Linux,
+ };
+
+ Some(Info {
+ os_type,
+ version,
+ codename: release.codename,
+ ..Default::default()
+ })
+}
+
+struct LsbRelease {
+ pub distribution: Option<String>,
+ pub version: Option<String>,
+ pub codename: Option<String>,
+}
+
+fn retrieve() -> Option<LsbRelease> {
+ match Command::new("lsb_release").arg("-a").output() {
+ Ok(output) => {
+ trace!("lsb_release command returned {:?}", output);
+ Some(parse(&String::from_utf8_lossy(&output.stdout)))
+ }
+ Err(e) => {
+ debug!("lsb_release command failed with {:?}", e);
+ None
+ }
+ }
+}
+
+fn parse(output: &str) -> LsbRelease {
+ trace!("Trying to parse {:?}", output);
+
+ let distribution = Matcher::PrefixedWord {
+ prefix: "Distributor ID:",
+ }
+ .find(output);
+
+ let codename = Matcher::PrefixedWord {
+ prefix: "Codename:",
+ }
+ .find(output)
+ .filter(|c| c != "n/a");
+
+ let version = Matcher::PrefixedVersion { prefix: "Release:" }.find(output);
+
+ trace!(
+ "Parsed as '{:?}' distribution and '{:?}' version",
+ distribution,
+ version
+ );
+
+ LsbRelease {
+ distribution,
+ version,
+ codename,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn debian() {
+ let parse_results = parse(file());
+ assert_eq!(parse_results.distribution, Some("Debian".to_string()));
+ assert_eq!(parse_results.version, Some("7.8".to_string()));
+ assert_eq!(parse_results.codename, Some("wheezy".to_string()));
+ }
+
+ #[test]
+ fn arch() {
+ let parse_results = parse(arch_file());
+ assert_eq!(parse_results.distribution, Some("Arch".to_string()));
+ assert_eq!(parse_results.version, Some("rolling".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn fedora() {
+ let parse_results = parse(fedora_file());
+ assert_eq!(parse_results.distribution, Some("Fedora".to_string()));
+ assert_eq!(parse_results.version, Some("26".to_string()));
+ assert_eq!(parse_results.codename, Some("TwentySix".to_string()));
+ }
+
+ #[test]
+ fn ubuntu() {
+ let parse_results = parse(ubuntu_file());
+ assert_eq!(parse_results.distribution, Some("Ubuntu".to_string()));
+ assert_eq!(parse_results.version, Some("16.04".to_string()));
+ assert_eq!(parse_results.codename, Some("xenial".to_string()));
+ }
+
+ #[test]
+ fn mint() {
+ let parse_results = parse(mint_file());
+ assert_eq!(parse_results.distribution, Some("Linuxmint".to_string()));
+ assert_eq!(parse_results.version, Some("20".to_string()));
+ assert_eq!(parse_results.codename, Some("ulyana".to_string()));
+ }
+
+ #[test]
+ fn nixos() {
+ let parse_results = parse(nixos_file());
+ assert_eq!(parse_results.distribution, Some("NixOS".to_string()));
+ assert_eq!(
+ parse_results.version,
+ Some("21.05pre275822.916ee862e87".to_string())
+ );
+ assert_eq!(parse_results.codename, Some("okapi".to_string()));
+ }
+
+ #[test]
+ fn amazon1() {
+ let parse_results = parse(amazon1_file());
+ assert_eq!(parse_results.distribution, Some("AmazonAMI".to_string()));
+ assert_eq!(parse_results.version, Some("2018.03".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn amazon2() {
+ let parse_results = parse(amazon2_file());
+ assert_eq!(parse_results.distribution, Some("Amazon".to_string()));
+ assert_eq!(parse_results.version, Some("2".to_string()));
+ assert_eq!(parse_results.codename, Some("Karoo".to_string()));
+ }
+
+ #[test]
+ fn redhat_enterprise_8() {
+ let parse_results = parse(rhel8_file());
+ assert_eq!(
+ parse_results.distribution,
+ Some("RedHatEnterprise".to_string())
+ );
+ assert_eq!(parse_results.version, Some("8.1".to_string()));
+ assert_eq!(parse_results.codename, Some("Ootpa".to_string()));
+ }
+
+ #[test]
+ fn redhat_enterprise_7() {
+ let parse_results = parse(rhel7_file());
+ assert_eq!(
+ parse_results.distribution,
+ Some("RedHatEnterpriseServer".to_string())
+ );
+ assert_eq!(parse_results.version, Some("7.7".to_string()));
+ assert_eq!(parse_results.codename, Some("Maipo".to_string()));
+ }
+
+ #[test]
+ fn redhat_enterprise_6() {
+ let parse_results = parse(rhel6_file());
+ assert_eq!(
+ parse_results.distribution,
+ Some("RedHatEnterpriseServer".to_string())
+ );
+ assert_eq!(parse_results.version, Some("6.10".to_string()));
+ assert_eq!(parse_results.codename, Some("Santiago".to_string()));
+ }
+
+ #[test]
+ fn suse_enterprise_15_1() {
+ let parse_results = parse(suse_enterprise15_1_file());
+ assert_eq!(parse_results.distribution, Some("SUSE".to_string()));
+ assert_eq!(parse_results.version, Some("15.1".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn suse_enterprise_12_5() {
+ let parse_results = parse(suse_enterprise12_5_file());
+ assert_eq!(parse_results.distribution, Some("SUSE".to_string()));
+ assert_eq!(parse_results.version, Some("12.5".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn open_suse_15_1() {
+ let parse_results = parse(open_suse_15_1_file());
+ assert_eq!(parse_results.distribution, Some("openSUSE".to_string()));
+ assert_eq!(parse_results.version, Some("15.1".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn oracle_linux_7_5() {
+ let parse_results = parse(oracle_server_linux_7_5_file());
+ assert_eq!(parse_results.distribution, Some("OracleServer".to_string()));
+ assert_eq!(parse_results.version, Some("7.5".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn oracle_linux_8_1() {
+ let parse_results = parse(oracle_server_linux_8_1_file());
+ assert_eq!(parse_results.distribution, Some("OracleServer".to_string()));
+ assert_eq!(parse_results.version, Some("8.1".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn pop_os_20_04_lts() {
+ let parse_results = parse(pop_os_20_04_lts_file());
+ assert_eq!(parse_results.distribution, Some("Pop".to_string()));
+ assert_eq!(parse_results.version, Some("20.04".to_string()));
+ assert_eq!(parse_results.codename, Some("focal".to_string()));
+ }
+
+ #[test]
+ fn solus_4_1() {
+ let parse_results = parse(solus_4_1_file());
+ assert_eq!(parse_results.distribution, Some("Solus".to_string()));
+ assert_eq!(parse_results.version, Some("4.1".to_string()));
+ assert_eq!(parse_results.codename, Some("fortitude".to_string()));
+ }
+
+ #[test]
+ fn manjaro() {
+ let parse_results = parse(manjaro_19_0_2_file());
+ assert_eq!(parse_results.distribution, Some("ManjaroLinux".to_string()));
+ assert_eq!(parse_results.version, Some("19.0.2".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn mariner() {
+ let parse_results = parse(mariner_file());
+ assert_eq!(parse_results.distribution, Some("Mariner".to_string()));
+ assert_eq!(parse_results.version, Some("2.0.20220210".to_string()));
+ assert_eq!(parse_results.codename, Some("Mariner".to_string()));
+ }
+
+ #[test]
+ fn endeavouros() {
+ let parse_results = parse(endeavouros_file());
+ assert_eq!(parse_results.distribution, Some("EndeavourOS".to_string()));
+ assert_eq!(parse_results.version, Some("rolling".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[test]
+ fn raspbian() {
+ let parse_results = parse(raspberry_os_file());
+ assert_eq!(parse_results.distribution, Some("Raspbian".to_string()));
+ assert_eq!(parse_results.version, Some("10".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ fn file() -> &'static str {
+ "\nDistributor ID: Debian\n\
+ Description: Debian GNU/Linux 7.8 (wheezy)\n\
+ Release: 7.8\n\
+ Codename: wheezy\n\
+ "
+ }
+
+ fn arch_file() -> &'static str {
+ "\nLSB Version: 1.4\n\
+ Distributor ID: Arch\n\
+ Description: Arch Linux\n\
+ Release: rolling\n\
+ Codename: n/a"
+ }
+
+ fn fedora_file() -> &'static str {
+ "\nLSB Version: :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch\n\
+ Distributor ID: Fedora\n\
+ Description: Fedora release 26 (Twenty Six)\n\
+ Release: 26\n\
+ Codename: TwentySix\n\
+ "
+ }
+
+ fn ubuntu_file() -> &'static str {
+ "Distributor ID: Ubuntu\n\
+ Description: Ubuntu 16.04.5 LTS\n\
+ Release: 16.04\n\
+ Codename: xenial"
+ }
+
+ fn mint_file() -> &'static str {
+ "Distributor ID: Linuxmint\n\
+ Description: Linux Mint 20\n\
+ Release: 20\n\
+ Codename: ulyana"
+ }
+
+ fn nixos_file() -> &'static str {
+ "Distributor ID: NixOS\n\
+ Description: NixOS 21.05 (Okapi)\n\
+ Release: 21.05pre275822.916ee862e87\n\
+ Codename: okapi"
+ }
+
+ // Amazon Linux 1 uses a separate Distributor ID and Release format from Amazon Linux 2
+ fn amazon1_file() -> &'static str {
+ "LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch\n\
+ Distributor ID: AmazonAMI\n\
+ Description: Amazon Linux AMI release 2018.03\n\
+ Release: 2018.03\n\
+ Codename: n/a\n\
+ "
+ }
+
+ // Amazon Linux 2 uses a separate Distributor ID and Release format from Amazon Linux 1
+ fn amazon2_file() -> &'static str {
+ "LSB Version: :core-4.1-amd64:core-4.1-noarch\n\
+ Distributor ID: Amazon\n\
+ Description: Amazon Linux release 2 (Karoo)\n\
+ Release: 2\n\
+ Codename: Karoo\n\
+ "
+ }
+
+ fn rhel8_file() -> &'static str {
+ "LSB Version: :core-4.1-amd64:core-4.1-noarch\n\
+ Distributor ID: RedHatEnterprise\n\
+ Description: Red Hat Enterprise Linux release 8.1 (Ootpa)\n\
+ Release: 8.1\n\
+ Codename: Ootpa\n\
+ "
+ }
+
+ fn rhel7_file() -> &'static str {
+ "LSB Version: :core-4.1-amd64:core-4.1-noarch\n\
+ Distributor ID: RedHatEnterpriseServer\n\
+ Description: Red Hat Enterprise Linux Server release 7.7 (Maipo)\n\
+ Release: 7.7\n\
+ Codename: Maipo\n\
+ "
+ }
+
+ fn rhel6_file() -> &'static str {
+ "LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch\n\
+ Distributor ID: RedHatEnterpriseServer\n\
+ Description: Red Hat Enterprise Linux Server release 6.10 (Santiago)\n\
+ Release: 6.10\n\
+ Codename: Santiago\n\
+ "
+ }
+
+ fn suse_enterprise15_1_file() -> &'static str {
+ "LSB Version: n/a\n\
+ Distributor ID: SUSE\n\
+ Description: SUSE Linux Enterprise Server 15 SP1\n\
+ Release: 15.1\n\
+ Codename: n/a\n\
+ "
+ }
+
+ fn suse_enterprise12_5_file() -> &'static str {
+ "LSB Version: n/a\n\
+ Distributor ID: SUSE\n\
+ Description: SUSE Linux Enterprise Server 12 SP5\n\
+ Release: 12.5\n\
+ Codename: n/a\n\
+ "
+ }
+
+ fn raspberry_os_file() -> &'static str {
+ "LSB Version: n/a\n\
+ Distributor ID: Raspbian\n\
+ Description: Raspbian GNU/Linux 10 (buster)\n\
+ Release: 10\n\
+ Codename: n/a\n\
+ "
+ }
+
+ fn open_suse_15_1_file() -> &'static str {
+ "LSB Version: n/a\n\
+ Distributor ID: openSUSE\n\
+ Description: openSUSE Leap 15.1\n\
+ Release: 15.1\n\
+ Codename: n/a\n\
+ "
+ }
+
+ fn oracle_server_linux_7_5_file() -> &'static str {
+ "LSB Version: :core-4.1-amd64:core-4.1-noarch\n\
+ Distributor ID: OracleServer\n\
+ Description: Oracle Linux Server release 7.5\n\
+ Release: 7.5\n\
+ Codename: n/a\n\
+ "
+ }
+
+ fn oracle_server_linux_8_1_file() -> &'static str {
+ "LSB Version: :core-4.1-amd64:core-4.1-noarch\n\
+ Distributor ID: OracleServer\n\
+ Description: Oracle Linux Server release 8.1\n\
+ Release: 8.1\n\
+ Codename: n/a\n\
+ "
+ }
+
+ fn pop_os_20_04_lts_file() -> &'static str {
+ "No LSB modules are available.\n\
+ Distributor ID: Pop\n\
+ Description: Pop!_OS 20.04 LTS\n\
+ Release: 20.04\n\
+ Codename: focal\n\
+ "
+ }
+
+ fn solus_4_1_file() -> &'static str {
+ "LSB Version: 1.4\n\
+ Distributor ID: Solus\n\
+ Description: Solus\n\
+ Release: 4.1\n\
+ Codename: fortitude\n\
+ "
+ }
+
+ fn manjaro_19_0_2_file() -> &'static str {
+ "LSB Version: n/a\n\
+ Distributor ID: ManjaroLinux\n\
+ Description: Manjaro Linux\n\
+ Release: 19.0.2\n\
+ Codename: n/a\n\
+ "
+ }
+
+ fn mariner_file() -> &'static str {
+ "LSB Version: n/a\n\
+ Distributor ID: Mariner\n\
+ Description: CBL-Mariner 2.0.20220210\n\
+ Release: 2.0.20220210\n\
+ Codename: Mariner\n\
+ "
+ }
+
+ fn endeavouros_file() -> &'static str {
+ "LSB Version: 1.4\n\
+ Distributor ID: EndeavourOS\n\
+ Description: EndeavourOS Linux\n\
+ Release: rolling\n\
+ Codename: n/a\n\
+ "
+ }
+}
diff --git a/vendor/os_info/src/linux/mod.rs b/vendor/os_info/src/linux/mod.rs
new file mode 100644
index 000000000..64d488342
--- /dev/null
+++ b/vendor/os_info/src/linux/mod.rs
@@ -0,0 +1,56 @@
+mod file_release;
+mod lsb_release;
+
+use log::trace;
+
+use crate::{bitness, Info, Type};
+
+pub fn current_platform() -> Info {
+ trace!("linux::current_platform is called");
+
+ let mut info = lsb_release::get()
+ .or_else(file_release::get)
+ .unwrap_or_else(|| Info::with_type(Type::Linux));
+ info.bitness = bitness::get();
+
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ match version.os_type() {
+ Type::Alpine
+ | Type::Amazon
+ | Type::Arch
+ | Type::CentOS
+ | Type::Debian
+ | Type::EndeavourOS
+ | Type::Fedora
+ | Type::Garuda
+ | Type::Gentoo
+ | Type::Linux
+ | Type::Manjaro
+ | Type::Mariner
+ | Type::NixOS
+ | Type::openSUSE
+ | Type::OracleLinux
+ | Type::Pop
+ | Type::Raspbian
+ | Type::Redhat
+ | Type::RedHatEnterprise
+ | Type::Solus
+ | Type::SUSE
+ | Type::Ubuntu
+ | Type::Mint => (),
+ os_type => {
+ panic!("Unexpected OS type: {}", os_type);
+ }
+ }
+ }
+}
diff --git a/vendor/os_info/src/linux/tests/Alpine/etc/alpine-release b/vendor/os_info/src/linux/tests/Alpine/etc/alpine-release
new file mode 100644
index 000000000..86562312c
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Alpine/etc/alpine-release
@@ -0,0 +1 @@
+A.B.C
diff --git a/vendor/os_info/src/linux/tests/Alpine_3_12/etc/os-release b/vendor/os_info/src/linux/tests/Alpine_3_12/etc/os-release
new file mode 100644
index 000000000..c2e6bc68a
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Alpine_3_12/etc/os-release
@@ -0,0 +1,6 @@
+NAME="Alpine Linux"
+ID=alpine
+VERSION_ID=3.12.0
+PRETTY_NAME="Alpine Linux v3.12"
+HOME_URL="https://alpinelinux.org/"
+BUG_REPORT_URL="https://bugs.alpinelinux.org/"
diff --git a/vendor/os_info/src/linux/tests/Amazon_1/etc/os-release b/vendor/os_info/src/linux/tests/Amazon_1/etc/os-release
new file mode 100644
index 000000000..b2b1a0796
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Amazon_1/etc/os-release
@@ -0,0 +1,9 @@
+NAME="Amazon Linux AMI"
+VERSION="2018.03"
+ID="amzn"
+ID_LIKE="rhel fedora"
+VERSION_ID="2018.03"
+PRETTY_NAME="Amazon Linux AMI 2018.03"
+ANSI_COLOR="0;33"
+CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
+HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
diff --git a/vendor/os_info/src/linux/tests/Amazon_2/etc/os-release b/vendor/os_info/src/linux/tests/Amazon_2/etc/os-release
new file mode 100644
index 000000000..07a45072f
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Amazon_2/etc/os-release
@@ -0,0 +1,9 @@
+NAME="Amazon Linux"
+VERSION="2"
+ID="amzn"
+ID_LIKE="centos rhel fedora"
+VERSION_ID="2"
+PRETTY_NAME="Amazon Linux 2"
+ANSI_COLOR="0;33"
+CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
+HOME_URL="https://amazonlinux.com/"
diff --git a/vendor/os_info/src/linux/tests/CentOS/etc/centos-release b/vendor/os_info/src/linux/tests/CentOS/etc/centos-release
new file mode 100644
index 000000000..359ef00dc
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/CentOS/etc/centos-release
@@ -0,0 +1 @@
+Centos Linux release XX
diff --git a/vendor/os_info/src/linux/tests/CentOS_7/etc/os-release b/vendor/os_info/src/linux/tests/CentOS_7/etc/os-release
new file mode 100644
index 000000000..c276e3ae5
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/CentOS_7/etc/os-release
@@ -0,0 +1,15 @@
+NAME="CentOS Linux"
+VERSION="7 (Core)"
+ID="centos"
+ID_LIKE="rhel fedora"
+VERSION_ID="7"
+PRETTY_NAME="CentOS Linux 7 (Core)"
+ANSI_COLOR="0;31"
+CPE_NAME="cpe:/o:centos:centos:7"
+HOME_URL="https://www.centos.org/"
+BUG_REPORT_URL="https://bugs.centos.org/"
+
+CENTOS_MANTISBT_PROJECT="CentOS-7"
+CENTOS_MANTISBT_PROJECT_VERSION="7"
+REDHAT_SUPPORT_PRODUCT="centos"
+REDHAT_SUPPORT_PRODUCT_VERSION="7"
diff --git a/vendor/os_info/src/linux/tests/CentOS_Stream/etc/os-release b/vendor/os_info/src/linux/tests/CentOS_Stream/etc/os-release
new file mode 100644
index 000000000..8948e12f4
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/CentOS_Stream/etc/os-release
@@ -0,0 +1,13 @@
+NAME="CentOS Stream"
+VERSION="8"
+ID="centos"
+ID_LIKE="rhel fedora"
+VERSION_ID="8"
+PLATFORM_ID="platform:el8"
+PRETTY_NAME="CentOS Stream 8"
+ANSI_COLOR="0;31"
+CPE_NAME="cpe:/o:centos:centos:8"
+HOME_URL="https://centos.org/"
+BUG_REPORT_URL="https://bugzilla.redhat.com/"
+REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux 8"
+REDHAT_SUPPORT_PRODUCT_VERSION="CentOS Stream"
diff --git a/vendor/os_info/src/linux/tests/CentOS_Unknown/etc/centos-release b/vendor/os_info/src/linux/tests/CentOS_Unknown/etc/centos-release
new file mode 100644
index 000000000..e6b865bc7
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/CentOS_Unknown/etc/centos-release
@@ -0,0 +1 @@
+Centos Linux
diff --git a/vendor/os_info/src/linux/tests/Fedora/etc/fedora-release b/vendor/os_info/src/linux/tests/Fedora/etc/fedora-release
new file mode 100644
index 000000000..f2641f4b5
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Fedora/etc/fedora-release
@@ -0,0 +1 @@
+Fedora release 26 (Twenty Six)
diff --git a/vendor/os_info/src/linux/tests/Fedora_32/etc/os-release b/vendor/os_info/src/linux/tests/Fedora_32/etc/os-release
new file mode 100644
index 000000000..234ecf163
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Fedora_32/etc/os-release
@@ -0,0 +1,21 @@
+NAME=Fedora
+VERSION="32 (Cloud Edition)"
+ID=fedora
+VERSION_ID=32
+VERSION_CODENAME=""
+PLATFORM_ID="platform:f32"
+PRETTY_NAME="Fedora 32 (Cloud Edition)"
+ANSI_COLOR="0;34"
+LOGO=fedora-logo-icon
+CPE_NAME="cpe:/o:fedoraproject:fedora:32"
+HOME_URL="https://fedoraproject.org/"
+DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f32/system-administrators-guide/"
+SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help"
+BUG_REPORT_URL="https://bugzilla.redhat.com/"
+REDHAT_BUGZILLA_PRODUCT="Fedora"
+REDHAT_BUGZILLA_PRODUCT_VERSION=32
+REDHAT_SUPPORT_PRODUCT="Fedora"
+REDHAT_SUPPORT_PRODUCT_VERSION=32
+PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
+VARIANT="Cloud Edition"
+VARIANT_ID=cloud
diff --git a/vendor/os_info/src/linux/tests/Fedora_35/etc/os-release b/vendor/os_info/src/linux/tests/Fedora_35/etc/os-release
new file mode 100644
index 000000000..9178d6d38
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Fedora_35/etc/os-release
@@ -0,0 +1,21 @@
+NAME="Fedora Linux"
+VERSION="35 (Workstation Edition)"
+ID=fedora
+VERSION_ID=35
+VERSION_CODENAME=""
+PLATFORM_ID="platform:f35"
+PRETTY_NAME="Fedora Linux 35 (Workstation Edition)"
+ANSI_COLOR="0;38;2;60;110;180"
+LOGO=fedora-logo-icon
+CPE_NAME="cpe:/o:fedoraproject:fedora:35"
+HOME_URL="https://fedoraproject.org/"
+DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f35/system-administrators-guide/"
+SUPPORT_URL="https://ask.fedoraproject.org/"
+BUG_REPORT_URL="https://bugzilla.redhat.com/"
+REDHAT_BUGZILLA_PRODUCT="Fedora"
+REDHAT_BUGZILLA_PRODUCT_VERSION=35
+REDHAT_SUPPORT_PRODUCT="Fedora"
+REDHAT_SUPPORT_PRODUCT_VERSION=35
+PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
+VARIANT="Workstation Edition"
+VARIANT_ID=workstation
diff --git a/vendor/os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release b/vendor/os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release
new file mode 100644
index 000000000..adc01153f
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release
@@ -0,0 +1 @@
+Fedora (Foo Bar)
diff --git a/vendor/os_info/src/linux/tests/Mariner/etc/mariner-release b/vendor/os_info/src/linux/tests/Mariner/etc/mariner-release
new file mode 100644
index 000000000..f4bceb49e
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Mariner/etc/mariner-release
@@ -0,0 +1,2 @@
+CBL-Mariner 2.0.20220210
+MARINER_BUILD_NUMBER=0d11c66
diff --git a/vendor/os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release b/vendor/os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release
new file mode 100644
index 000000000..d64fd5303
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release
@@ -0,0 +1 @@
+CBL-Mariner \ No newline at end of file
diff --git a/vendor/os_info/src/linux/tests/Mint/etc/os-release b/vendor/os_info/src/linux/tests/Mint/etc/os-release
new file mode 100644
index 000000000..825d92877
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Mint/etc/os-release
@@ -0,0 +1,12 @@
+NAME="Linux Mint"
+VERSION="20 (Ulyana)"
+ID=linuxmint
+ID_LIKE=ubuntu
+PRETTY_NAME="Linux Mint 20"
+VERSION_ID="20"
+HOME_URL="https://www.linuxmint.com/"
+SUPPORT_URL="https://forums.linuxmint.com/"
+BUG_REPORT_URL="http://linuxmint-troubleshooting-guide.readthedocs.io/en/latest/"
+PRIVACY_POLICY_URL="https://www.linuxmint.com/"
+VERSION_CODENAME=ulyana
+UBUNTU_CODENAME=focal
diff --git a/vendor/os_info/src/linux/tests/NixOS/etc/os-release b/vendor/os_info/src/linux/tests/NixOS/etc/os-release
new file mode 100644
index 000000000..b93cf4d12
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/NixOS/etc/os-release
@@ -0,0 +1,11 @@
+NAME=NixOS
+ID=nixos
+VERSION="21.05pre275822.916ee862e87 (Okapi)"
+VERSION_CODENAME=okapi
+VERSION_ID="21.05pre275822.916ee862e87"
+PRETTY_NAME="NixOS 21.05 (Okapi)"
+LOGO="nix-snowflake"
+HOME_URL="https://nixos.org/"
+DOCUMENTATION_URL="https://nixos.org/learn.html"
+SUPPORT_URL="https://nixos.org/community.html"
+BUG_REPORT_URL="https://github.com/NixOS/nixpkgs/issues"
diff --git a/vendor/os_info/src/linux/tests/OracleLinux/etc/os-release b/vendor/os_info/src/linux/tests/OracleLinux/etc/os-release
new file mode 100644
index 000000000..1594788f3
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/OracleLinux/etc/os-release
@@ -0,0 +1,18 @@
+NAME="Oracle Linux Server"
+VERSION="8.1"
+ID="ol"
+ID_LIKE="fedora"
+VARIANT="Server"
+VARIANT_ID="server"
+VERSION_ID="8.1"
+PLATFORM_ID="platform:el8"
+PRETTY_NAME="Oracle Linux Server 8.1"
+ANSI_COLOR="0;31"
+CPE_NAME="cpe:/o:oracle:linux:8:1:server"
+HOME_URL="https://linux.oracle.com/"
+BUG_REPORT_URL="https://bugzilla.oracle.com/"
+
+ORACLE_BUGZILLA_PRODUCT="Oracle Linux 8"
+ORACLE_BUGZILLA_PRODUCT_VERSION=8.1
+ORACLE_SUPPORT_PRODUCT="Oracle Linux"
+ORACLE_SUPPORT_PRODUCT_VERSION=8.1
diff --git a/vendor/os_info/src/linux/tests/OracleLinux/etc/redhat-release b/vendor/os_info/src/linux/tests/OracleLinux/etc/redhat-release
new file mode 100644
index 000000000..994041ed8
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/OracleLinux/etc/redhat-release
@@ -0,0 +1 @@
+Redhat Linux release XX \ No newline at end of file
diff --git a/vendor/os_info/src/linux/tests/RedHatEnterprise/etc/redhat-release b/vendor/os_info/src/linux/tests/RedHatEnterprise/etc/redhat-release
new file mode 100644
index 000000000..ff4da1dea
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/RedHatEnterprise/etc/redhat-release
@@ -0,0 +1 @@
+Redhat Linux release XX
diff --git a/vendor/os_info/src/linux/tests/RedHatEnterprise_7/etc/os-release b/vendor/os_info/src/linux/tests/RedHatEnterprise_7/etc/os-release
new file mode 100644
index 000000000..ec038b12a
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/RedHatEnterprise_7/etc/os-release
@@ -0,0 +1,17 @@
+NAME="Red Hat Enterprise Linux Server"
+VERSION="7.9 (Maipo)"
+ID="rhel"
+ID_LIKE="fedora"
+VARIANT="Server"
+VARIANT_ID="server"
+VERSION_ID="7.9"
+PRETTY_NAME="Red Hat Enterprise Linux Server 7.9 (Maipo)"
+ANSI_COLOR="0;31"
+CPE_NAME="cpe:/o:redhat:enterprise_linux:7.9:GA:server"
+HOME_URL="https://www.redhat.com/"
+BUG_REPORT_URL="https://bugzilla.redhat.com/"
+
+REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7"
+REDHAT_BUGZILLA_PRODUCT_VERSION=7.9
+REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
+REDHAT_SUPPORT_PRODUCT_VERSION="7.9"
diff --git a/vendor/os_info/src/linux/tests/RedHatEnterprise_8/etc/os-release b/vendor/os_info/src/linux/tests/RedHatEnterprise_8/etc/os-release
new file mode 100644
index 000000000..1d5515ba6
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/RedHatEnterprise_8/etc/os-release
@@ -0,0 +1,16 @@
+NAME="Red Hat Enterprise Linux"
+VERSION="8.2 (Ootpa)"
+ID="rhel"
+ID_LIKE="fedora"
+VERSION_ID="8.2"
+PLATFORM_ID="platform:el8"
+PRETTY_NAME="Red Hat Enterprise Linux 8.2 (Ootpa)"
+ANSI_COLOR="0;31"
+CPE_NAME="cpe:/o:redhat:enterprise_linux:8.2:GA"
+HOME_URL="https://www.redhat.com/"
+BUG_REPORT_URL="https://bugzilla.redhat.com/"
+
+REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 8"
+REDHAT_BUGZILLA_PRODUCT_VERSION=8.2
+REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
+REDHAT_SUPPORT_PRODUCT_VERSION="8.2"
diff --git a/vendor/os_info/src/linux/tests/RedHatEnterprise_Unknown/etc/redhat-release b/vendor/os_info/src/linux/tests/RedHatEnterprise_Unknown/etc/redhat-release
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/RedHatEnterprise_Unknown/etc/redhat-release
diff --git a/vendor/os_info/src/linux/tests/SUSE_12/etc/os-release b/vendor/os_info/src/linux/tests/SUSE_12/etc/os-release
new file mode 100644
index 000000000..2de3f28ed
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/SUSE_12/etc/os-release
@@ -0,0 +1,7 @@
+NAME="SLES"
+VERSION="12-SP5"
+VERSION_ID="12.5"
+PRETTY_NAME="SUSE Linux Enterprise Server 12 SP5"
+ID="sles"
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:suse:sles:12:sp5"
diff --git a/vendor/os_info/src/linux/tests/SUSE_15/etc/os-release b/vendor/os_info/src/linux/tests/SUSE_15/etc/os-release
new file mode 100644
index 000000000..54fafb50b
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/SUSE_15/etc/os-release
@@ -0,0 +1,8 @@
+NAME="SLES"
+VERSION="15-SP2"
+VERSION_ID="15.2"
+PRETTY_NAME="SUSE Linux Enterprise Server 15 SP2"
+ID="sles"
+ID_LIKE="suse"
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:suse:sles:15:sp2"
diff --git a/vendor/os_info/src/linux/tests/Ubuntu/etc/os-release b/vendor/os_info/src/linux/tests/Ubuntu/etc/os-release
new file mode 100644
index 000000000..2369e58a0
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Ubuntu/etc/os-release
@@ -0,0 +1,12 @@
+NAME="Ubuntu"
+VERSION="18.10 (Cosmic Cuttlefish)"
+ID=ubuntu
+ID_LIKE=debian
+PRETTY_NAME="Ubuntu 18.10"
+VERSION_ID="18.10"
+HOME_URL="https://www.ubuntu.com/"
+SUPPORT_URL="https://help.ubuntu.com/"
+BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
+PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
+VERSION_CODENAME=cosmic
+UBUNTU_CODENAME=cosmic
diff --git a/vendor/os_info/src/linux/tests/none_invalid_os_release/etc/os-release b/vendor/os_info/src/linux/tests/none_invalid_os_release/etc/os-release
new file mode 100644
index 000000000..92258e650
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/none_invalid_os_release/etc/os-release
@@ -0,0 +1,2 @@
+ID="Lorem ipsum dolor sit amet"
+VERSION_ID="It's all greek to me"
diff --git a/vendor/os_info/src/macos/mod.rs b/vendor/os_info/src/macos/mod.rs
new file mode 100644
index 000000000..0c93a9713
--- /dev/null
+++ b/vendor/os_info/src/macos/mod.rs
@@ -0,0 +1,106 @@
+use std::process::Command;
+
+use log::{trace, warn};
+
+use crate::{bitness, matcher::Matcher, Info, Type, Version};
+
+pub fn current_platform() -> Info {
+ trace!("macos::current_platform is called");
+
+ let info = Info {
+ os_type: Type::Macos,
+ version: version(),
+ bitness: bitness::get(),
+ ..Default::default()
+ };
+ trace!("Returning {:?}", info);
+ info
+}
+
+fn version() -> Version {
+ match product_version() {
+ None => Version::Unknown,
+ Some(val) => Version::from_string(val),
+ }
+}
+
+fn product_version() -> Option<String> {
+ match Command::new("sw_vers").output() {
+ Ok(val) => {
+ let output = String::from_utf8_lossy(&val.stdout);
+ trace!("sw_vers command returned {:?}", output);
+ parse(&output)
+ }
+ Err(e) => {
+ warn!("sw_vers command failed with {:?}", e);
+ None
+ }
+ }
+}
+
+fn parse(sw_vers_output: &str) -> Option<String> {
+ Matcher::PrefixedVersion {
+ prefix: "ProductVersion:",
+ }
+ .find(sw_vers_output)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::{assert_eq, assert_ne};
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::Macos, version.os_type());
+ }
+
+ #[test]
+ fn os_version() {
+ let version = version();
+ assert_ne!(Version::Unknown, version);
+ }
+
+ #[test]
+ fn string_product_version() {
+ let version = product_version();
+ assert!(version.is_some());
+ }
+
+ #[test]
+ fn parse_version() {
+ let parse_output = parse(sw_vers_output());
+ assert_eq!(parse_output, Some("10.10.5".to_string()));
+ }
+
+ fn sw_vers_output() -> &'static str {
+ "ProductName: Mac OS X\n\
+ ProductVersion: 10.10.5\n\
+ BuildVersion: 14F27"
+ }
+
+ #[test]
+ fn parse_beta_version() {
+ let parse_output = parse(sw_vers_output_beta());
+ assert_eq!(parse_output, Some("10.15".to_string()));
+ }
+
+ fn sw_vers_output_beta() -> &'static str {
+ "ProductName: Mac OS X\n\
+ ProductVersion: 10.15\n\
+ BuildVersion: 19A546d"
+ }
+
+ #[test]
+ fn parse_double_digit_patch_version() {
+ let parse_output = parse(sw_vers_output_double_digit_patch_version());
+ assert_eq!(parse_output, Some("10.15.21".to_string()));
+ }
+
+ fn sw_vers_output_double_digit_patch_version() -> &'static str {
+ "ProductName: Mac OS X\n\
+ ProductVersion: 10.15.21\n\
+ BuildVersion: ABCD123"
+ }
+}
diff --git a/vendor/os_info/src/matcher.rs b/vendor/os_info/src/matcher.rs
new file mode 100644
index 000000000..fcc31bc59
--- /dev/null
+++ b/vendor/os_info/src/matcher.rs
@@ -0,0 +1,148 @@
+/// An implementation to match on simple strings.
+#[derive(Debug, Clone)]
+#[allow(dead_code)]
+pub enum Matcher {
+ /// Considers the entire string (trimmed) to be the match.
+ AllTrimmed,
+
+ /// After finding the `prefix` followed by one or more spaces, returns the following word.
+ PrefixedWord { prefix: &'static str },
+
+ /// Similar to `PrefixedWord`, but only if the word is a valid version.
+ PrefixedVersion { prefix: &'static str },
+
+ /// Takes a set of lines (separated by `\n`) and searches for the value in a key/value pair
+ /// separated by the `=` character. For example `VERSION_ID="8.1"`.
+ KeyValue { key: &'static str },
+}
+
+impl Matcher {
+ /// Find the match on the input `string`.
+ pub fn find(&self, string: &str) -> Option<String> {
+ match *self {
+ Self::AllTrimmed => Some(string.trim().to_string()),
+ Self::PrefixedWord { prefix } => find_prefixed_word(string, prefix).map(str::to_owned),
+ Self::PrefixedVersion { prefix } => find_prefixed_word(string, prefix)
+ .filter(|&v| is_valid_version(v))
+ .map(str::to_owned),
+ Self::KeyValue { key } => find_by_key(string, key).map(str::to_owned),
+ }
+ }
+}
+
+fn find_by_key<'a>(string: &'a str, key: &str) -> Option<&'a str> {
+ let key = [key, "="].concat();
+ for line in string.lines() {
+ if line.starts_with(&key) {
+ return Some(line[key.len()..].trim_matches(|c: char| c == '"' || c.is_whitespace()));
+ }
+ }
+
+ None
+}
+
+fn find_prefixed_word<'a>(string: &'a str, prefix: &str) -> Option<&'a str> {
+ if let Some(prefix_start) = string.find(prefix) {
+ // Ignore prefix and leading whitespace
+ let string = &string[prefix_start + prefix.len()..].trim_start();
+
+ // Find where the word boundary ends
+ let word_end = string
+ .find(|c: char| c.is_whitespace())
+ .unwrap_or(string.len());
+ let string = &string[..word_end];
+
+ Some(string)
+ } else {
+ None
+ }
+}
+
+fn is_valid_version(word: &str) -> bool {
+ !word.starts_with('.') && !word.ends_with('.')
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn trimmed() {
+ let data = [
+ ("", Some("")),
+ ("test", Some("test")),
+ (" test", Some("test")),
+ ("test ", Some("test")),
+ (" test ", Some("test")),
+ ];
+
+ let matcher = Matcher::AllTrimmed;
+
+ for (input, expected) in &data {
+ let result = matcher.find(input);
+ assert_eq!(result.as_deref(), *expected);
+ }
+ }
+
+ #[test]
+ fn prefixed_word() {
+ let data = [
+ ("", None),
+ ("test", Some("")),
+ ("test1", Some("1")),
+ ("test 1", Some("1")),
+ (" test 1", Some("1")),
+ ("test 1.2.3", Some("1.2.3")),
+ (" test 1.2.3", Some("1.2.3")),
+ ];
+
+ let matcher = Matcher::PrefixedWord { prefix: "test" };
+
+ for (input, expected) in &data {
+ let result = matcher.find(input);
+ assert_eq!(result.as_deref(), *expected);
+ }
+ }
+
+ #[test]
+ fn prefixed_version() {
+ let data = [
+ ("", None),
+ ("test", Some("")),
+ ("test 1", Some("1")),
+ ("test .1", None),
+ ("test 1.", None),
+ ("test .1.", None),
+ (" test 1", Some("1")),
+ ("test 1.2.3", Some("1.2.3")),
+ (" test 1.2.3", Some("1.2.3")),
+ ];
+
+ let matcher = Matcher::PrefixedVersion { prefix: "test" };
+
+ for (input, expected) in &data {
+ let result = matcher.find(input);
+ assert_eq!(result.as_deref(), *expected);
+ }
+ }
+
+ #[test]
+ fn key_value() {
+ let data = [
+ ("", None),
+ ("key", None),
+ ("key=value", Some("value")),
+ ("key=1", Some("1")),
+ ("key=\"1\"", Some("1")),
+ ("key=\"CentOS Linux\"", Some("CentOS Linux")),
+ ];
+
+ let matcher = Matcher::KeyValue { key: "key" };
+
+ for (input, expected) in &data {
+ let result = matcher.find(input);
+ assert_eq!(result.as_deref(), *expected);
+ }
+ }
+}
diff --git a/vendor/os_info/src/netbsd/mod.rs b/vendor/os_info/src/netbsd/mod.rs
new file mode 100644
index 000000000..d5ab97bfb
--- /dev/null
+++ b/vendor/os_info/src/netbsd/mod.rs
@@ -0,0 +1,35 @@
+use std::process::Command;
+
+use log::{error, trace};
+
+use crate::{bitness, uname::uname, Info, Type, Version};
+
+pub fn current_platform() -> Info {
+ trace!("netbsd::current_platform is called");
+
+ let version = uname()
+ .map(Version::from_string)
+ .unwrap_or_else(|| Version::Unknown);
+
+ let info = Info {
+ os_type: Type::NetBSD,
+ version,
+ bitness: bitness::get(),
+ ..Default::default()
+ };
+
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::NetBSD, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/openbsd/mod.rs b/vendor/os_info/src/openbsd/mod.rs
new file mode 100644
index 000000000..897fc4aeb
--- /dev/null
+++ b/vendor/os_info/src/openbsd/mod.rs
@@ -0,0 +1,35 @@
+use std::process::Command;
+
+use log::{error, trace};
+
+use crate::{bitness, uname::uname, Info, Type, Version};
+
+pub fn current_platform() -> Info {
+ trace!("openbsd::current_platform is called");
+
+ let version = uname()
+ .map(Version::from_string)
+ .unwrap_or_else(|| Version::Unknown);
+
+ let info = Info {
+ os_type: Type::OpenBSD,
+ version,
+ bitness: bitness::get(),
+ ..Default::default()
+ };
+
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::OpenBSD, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/os_type.rs b/vendor/os_info/src/os_type.rs
new file mode 100644
index 000000000..8cab07b8e
--- /dev/null
+++ b/vendor/os_info/src/os_type.rs
@@ -0,0 +1,162 @@
+use std::fmt::{self, Display, Formatter};
+
+/// A list of supported operating system types.
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
+#[non_exhaustive]
+pub enum Type {
+ /// Alpine Linux (<https://en.wikipedia.org/wiki/Alpine_Linux>).
+ Alpine,
+ /// Amazon Linux AMI (<https://en.wikipedia.org/wiki/Amazon_Machine_Image#Amazon_Linux_AMI>).
+ Amazon,
+ /// Android (<https://en.wikipedia.org/wiki/Android_(operating_system)>).
+ Android,
+ /// Arch Linux (<https://en.wikipedia.org/wiki/Arch_Linux>).
+ Arch,
+ /// CentOS (<https://en.wikipedia.org/wiki/CentOS>).
+ CentOS,
+ /// Debian (<https://en.wikipedia.org/wiki/Debian>).
+ Debian,
+ /// DragonFly BSD (<https://en.wikipedia.org/wiki/DragonFly_BSD>).
+ DragonFly,
+ /// Emscripten (<https://en.wikipedia.org/wiki/Emscripten>).
+ Emscripten,
+ /// EndeavourOS (<https://en.wikipedia.org/wiki/EndeavourOS>).
+ EndeavourOS,
+ /// Fedora (<https://en.wikipedia.org/wiki/Fedora_(operating_system)>).
+ Fedora,
+ /// FreeBSD (<https://en.wikipedia.org/wiki/FreeBSD>).
+ FreeBSD,
+ /// Garuda Linux (<https://en.wikipedia.org/wiki/Garuda_Linux>)
+ Garuda,
+ /// Gentoo Linux (<https://en.wikipedia.org/wiki/Gentoo_Linux>).
+ Gentoo,
+ /// HardenedBSD (https://hardenedbsd.org/).
+ HardenedBSD,
+ /// Illumos (https://en.wikipedia.org/wiki/Illumos).
+ Illumos,
+ /// Linux based operating system (<https://en.wikipedia.org/wiki/Linux>).
+ Linux,
+ /// Mac OS X/OS X/macOS (<https://en.wikipedia.org/wiki/MacOS>).
+ Macos,
+ /// Manjaro (<https://en.wikipedia.org/wiki/Manjaro>).
+ Manjaro,
+ /// Mariner (<https://en.wikipedia.org/wiki/CBL-Mariner>).
+ Mariner,
+ /// MidnightBSD (<https://en.wikipedia.org/wiki/MidnightBSD>).
+ MidnightBSD,
+ /// Mint (<https://en.wikipedia.org/wiki/Linux_Mint>).
+ Mint,
+ /// NetBSD (<https://en.wikipedia.org/wiki/NetBSD>).
+ NetBSD,
+ /// NixOS (<https://en.wikipedia.org/wiki/NixOS>).
+ NixOS,
+ /// OpenBSD (<https://en.wikipedia.org/wiki/OpenBSD>).
+ OpenBSD,
+ /// openSUSE (<https://en.wikipedia.org/wiki/OpenSUSE>).
+ openSUSE,
+ /// Oracle Linux (<https://en.wikipedia.org/wiki/Oracle_Linux>).
+ OracleLinux,
+ /// Pop!_OS (<https://en.wikipedia.org/wiki/Pop!_OS>)
+ Pop,
+ /// Raspberry Pi OS (<https://en.wikipedia.org/wiki/Raspberry_Pi_OS>).
+ Raspbian,
+ /// Red Hat Linux (<https://en.wikipedia.org/wiki/Red_Hat_Linux>).
+ Redhat,
+ /// Red Hat Enterprise Linux (<https://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux>).
+ RedHatEnterprise,
+ /// Redox (<https://en.wikipedia.org/wiki/Redox_(operating_system)>).
+ Redox,
+ /// Solus (<https://en.wikipedia.org/wiki/Solus_(operating_system)>).
+ Solus,
+ /// SUSE Linux Enterprise Server (<https://en.wikipedia.org/wiki/SUSE_Linux_Enterprise>).
+ SUSE,
+ /// Ubuntu (<https://en.wikipedia.org/wiki/Ubuntu_(operating_system)>).
+ Ubuntu,
+ /// Unknown operating system.
+ Unknown,
+ /// Windows (<https://en.wikipedia.org/wiki/Microsoft_Windows>).
+ Windows,
+}
+
+impl Default for Type {
+ fn default() -> Self {
+ Type::Unknown
+ }
+}
+
+impl Display for Type {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match *self {
+ Type::Alpine => write!(f, "Alpine Linux"),
+ Type::Amazon => write!(f, "Amazon Linux AMI"),
+ Type::Arch => write!(f, "Arch Linux"),
+ Type::DragonFly => write!(f, "DragonFly BSD"),
+ Type::Garuda => write!(f, "Garuda Linux"),
+ Type::Gentoo => write!(f, "Gentoo Linux"),
+ Type::Illumos => write!(f, "illumos"),
+ Type::Macos => write!(f, "Mac OS"),
+ Type::MidnightBSD => write!(f, "Midnight BSD"),
+ Type::Mint => write!(f, "Linux Mint"),
+ Type::Pop => write!(f, "Pop!_OS"),
+ Type::Raspbian => write!(f, "Raspberry Pi OS"),
+ Type::Redhat => write!(f, "Red Hat Linux"),
+ Type::RedHatEnterprise => write!(f, "Red Hat Enterprise Linux"),
+ Type::SUSE => write!(f, "SUSE Linux Enterprise Server"),
+ _ => write!(f, "{:?}", self),
+ }
+ }
+}
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn default() {
+ assert_eq!(Type::Unknown, Type::default());
+ }
+
+ #[test]
+ fn display() {
+ let data = [
+ (Type::Alpine, "Alpine Linux"),
+ (Type::Amazon, "Amazon Linux AMI"),
+ (Type::Android, "Android"),
+ (Type::Arch, "Arch Linux"),
+ (Type::CentOS, "CentOS"),
+ (Type::Debian, "Debian"),
+ (Type::DragonFly, "DragonFly BSD"),
+ (Type::Emscripten, "Emscripten"),
+ (Type::EndeavourOS, "EndeavourOS"),
+ (Type::Fedora, "Fedora"),
+ (Type::Garuda, "Garuda Linux"),
+ (Type::Gentoo, "Gentoo Linux"),
+ (Type::FreeBSD, "FreeBSD"),
+ (Type::Linux, "Linux"),
+ (Type::Macos, "Mac OS"),
+ (Type::Manjaro, "Manjaro"),
+ (Type::Mint, "Linux Mint"),
+ (Type::NetBSD, "NetBSD"),
+ (Type::NixOS, "NixOS"),
+ (Type::OpenBSD, "OpenBSD"),
+ (Type::openSUSE, "openSUSE"),
+ (Type::OracleLinux, "OracleLinux"),
+ (Type::Pop, "Pop!_OS"),
+ (Type::Raspbian, "Raspberry Pi OS"),
+ (Type::Redhat, "Red Hat Linux"),
+ (Type::RedHatEnterprise, "Red Hat Enterprise Linux"),
+ (Type::Redox, "Redox"),
+ (Type::Solus, "Solus"),
+ (Type::SUSE, "SUSE Linux Enterprise Server"),
+ (Type::Ubuntu, "Ubuntu"),
+ (Type::Unknown, "Unknown"),
+ (Type::Windows, "Windows"),
+ ];
+
+ for (t, expected) in &data {
+ assert_eq!(&t.to_string(), expected);
+ }
+ }
+}
diff --git a/vendor/os_info/src/redox/mod.rs b/vendor/os_info/src/redox/mod.rs
new file mode 100644
index 000000000..1efd59113
--- /dev/null
+++ b/vendor/os_info/src/redox/mod.rs
@@ -0,0 +1,54 @@
+// spell-checker:ignore uname
+
+use std::{fs::File, io::Read};
+
+use log::{error, trace};
+
+use crate::{Bitness, Info, Type, Version};
+
+const UNAME_FILE: &str = "sys:uname";
+
+pub fn current_platform() -> Info {
+ trace!("redox::current_platform is called");
+
+ let version = get_version()
+ .map(Version::from_string)
+ .unwrap_or_else(|| Version::Unknown);
+ let info = Info {
+ os_type: Type::Redox,
+ version,
+ bitness: Bitness::Unknown,
+ ..Default::default()
+ };
+ trace!("Returning {:?}", info);
+ info
+}
+
+fn get_version() -> Option<String> {
+ let mut file = match File::open(UNAME_FILE) {
+ Ok(file) => file,
+ Err(e) => {
+ error!("Unable to open {} file: {:?}", UNAME_FILE, e);
+ return None;
+ }
+ };
+
+ let mut version = String::new();
+ if let Err(e) = file.read_to_string(&mut version) {
+ error!("Unable to read {} file: {:?}", UNAME_FILE, e);
+ return None;
+ }
+ Some(version)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::Redox, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/uname.rs b/vendor/os_info/src/uname.rs
new file mode 100644
index 000000000..f4417e882
--- /dev/null
+++ b/vendor/os_info/src/uname.rs
@@ -0,0 +1,32 @@
+use std::process::Command;
+
+use log::error;
+
+pub fn uname() -> Option<String> {
+ Command::new("uname")
+ .arg("-r")
+ .output()
+ .map_err(|e| {
+ error!("Failed to invoke 'uname': {:?}", e);
+ })
+ .ok()
+ .and_then(|out| {
+ if out.status.success() {
+ Some(String::from_utf8_lossy(&out.stdout).trim_end().to_owned())
+ } else {
+ log::error!("'uname' invocation error: {:?}", out);
+ None
+ }
+ })
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn uname_nonempty() {
+ let val = uname().expect("uname failed");
+ assert!(!val.is_empty());
+ }
+}
diff --git a/vendor/os_info/src/unknown/mod.rs b/vendor/os_info/src/unknown/mod.rs
new file mode 100644
index 000000000..fbebe213d
--- /dev/null
+++ b/vendor/os_info/src/unknown/mod.rs
@@ -0,0 +1,20 @@
+use log::trace;
+
+use crate::{Info, Type};
+
+pub fn current_platform() -> Info {
+ trace!("unknown::current_platform is called");
+ Info::unknown()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::Unknown, version.os_type());
+ }
+}
diff --git a/vendor/os_info/src/version.rs b/vendor/os_info/src/version.rs
new file mode 100644
index 000000000..20a2c4a61
--- /dev/null
+++ b/vendor/os_info/src/version.rs
@@ -0,0 +1,150 @@
+use std::fmt::{self, Display, Formatter};
+
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+
+/// Operating system version.
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub enum Version {
+ /// Unknown version.
+ Unknown,
+ /// Semantic version (major.minor.patch).
+ Semantic(u64, u64, u64),
+ /// Rolling version. Optionally contains the release date in the string format.
+ Rolling(Option<String>),
+ /// Custom version format.
+ Custom(String),
+}
+
+impl Version {
+ /// Constructs `VersionType` from the given string.
+ ///
+ /// Returns `VersionType::Unknown` if the string is empty. If it can be parsed as a semantic
+ /// version, then `VersionType::Semantic`, otherwise `VersionType::Custom`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::Version;
+ ///
+ /// let v = Version::from_string("custom");
+ /// assert_eq!(Version::Custom("custom".to_owned()), v);
+ ///
+ /// let v = Version::from_string("1.2.3");
+ /// assert_eq!(Version::Semantic(1, 2, 3), v);
+ /// ```
+ pub fn from_string<S: Into<String> + AsRef<str>>(s: S) -> Self {
+ if s.as_ref().is_empty() {
+ Self::Unknown
+ } else if let Some((major, minor, patch)) = parse_version(s.as_ref()) {
+ Self::Semantic(major, minor, patch)
+ } else {
+ Self::Custom(s.into())
+ }
+ }
+}
+
+impl Default for Version {
+ fn default() -> Self {
+ Version::Unknown
+ }
+}
+
+impl Display for Version {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match *self {
+ Self::Unknown => f.write_str("Unknown"),
+ Self::Semantic(major, minor, patch) => write!(f, "{}.{}.{}", major, minor, patch),
+ Self::Rolling(ref date) => {
+ let date = match date {
+ Some(date) => format!(" ({})", date),
+ None => "".to_owned(),
+ };
+ write!(f, "Rolling Release{}", date)
+ }
+ Self::Custom(ref version) => write!(f, "{}", version),
+ }
+ }
+}
+
+fn parse_version(s: &str) -> Option<(u64, u64, u64)> {
+ let mut iter = s.trim().split_terminator('.').fuse();
+
+ let major = iter.next().and_then(|s| s.parse().ok())?;
+ let minor = iter.next().unwrap_or("0").parse().ok()?;
+ let patch = iter.next().unwrap_or("0").parse().ok()?;
+
+ if iter.next().is_some() {
+ return None;
+ }
+
+ Some((major, minor, patch))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn parse_semantic_version() {
+ let data = [
+ ("", None),
+ ("version", None),
+ ("1", Some((1, 0, 0))),
+ ("1.", Some((1, 0, 0))),
+ ("1.2", Some((1, 2, 0))),
+ ("1.2.", Some((1, 2, 0))),
+ ("1.2.3", Some((1, 2, 3))),
+ ("1.2.3.", Some((1, 2, 3))),
+ ("1.2.3. ", Some((1, 2, 3))),
+ (" 1.2.3.", Some((1, 2, 3))),
+ (" 1.2.3. ", Some((1, 2, 3))),
+ ("1.2.3.4", None),
+ ("1.2.3.4.5.6.7.8.9", None),
+ ];
+
+ for (s, expected) in &data {
+ let result = parse_version(s);
+ assert_eq!(expected, &result);
+ }
+ }
+
+ #[test]
+ fn from_string() {
+ let custom_version = "some version";
+ let data = [
+ ("", Version::Unknown),
+ ("1.2.3", Version::Semantic(1, 2, 3)),
+ (custom_version, Version::Custom(custom_version.to_owned())),
+ ];
+
+ for (s, expected) in &data {
+ let version = Version::from_string(*s);
+ assert_eq!(expected, &version);
+ }
+ }
+
+ #[test]
+ fn default() {
+ assert_eq!(Version::Unknown, Version::default());
+ }
+
+ #[test]
+ fn display() {
+ let data = [
+ (Version::Unknown, "Unknown"),
+ (Version::Semantic(1, 5, 0), "1.5.0"),
+ (Version::Rolling(None), "Rolling Release"),
+ (
+ Version::Rolling(Some("date".to_owned())),
+ "Rolling Release (date)",
+ ),
+ ];
+
+ for (version, expected) in &data {
+ assert_eq!(expected, &version.to_string());
+ }
+ }
+}
diff --git a/vendor/os_info/src/windows/mod.rs b/vendor/os_info/src/windows/mod.rs
new file mode 100644
index 000000000..4e57d4a62
--- /dev/null
+++ b/vendor/os_info/src/windows/mod.rs
@@ -0,0 +1,26 @@
+mod winapi;
+
+use log::trace;
+
+use crate::Info;
+
+pub fn current_platform() -> Info {
+ trace!("windows::current_platform is called");
+ let info = winapi::get();
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::Type;
+ use pretty_assertions::assert_eq;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ assert_eq!(Type::Windows, version.os_type());
+ assert!(version.edition().is_some());
+ }
+}
diff --git a/vendor/os_info/src/windows/winapi.rs b/vendor/os_info/src/windows/winapi.rs
new file mode 100644
index 000000000..59e3f30d9
--- /dev/null
+++ b/vendor/os_info/src/windows/winapi.rs
@@ -0,0 +1,371 @@
+// spell-checker:ignore dword, minwindef, ntdef, ntdll, ntstatus, osversioninfoex, osversioninfoexa
+// spell-checker:ignore osversioninfoexw, serverr, sysinfoapi, winnt, winuser, pbool, libloaderapi
+// spell-checker:ignore lpcstr, processthreadsapi, farproc, lstatus, wchar, lpbyte, hkey, winerror
+// spell-checker:ignore osstr, winreg
+
+#![allow(unsafe_code)]
+
+use std::{
+ ffi::{OsStr, OsString},
+ mem,
+ os::windows::ffi::{OsStrExt, OsStringExt},
+ ptr,
+};
+
+use winapi::{
+ shared::{
+ minwindef::{DWORD, FARPROC, LPBYTE},
+ ntdef::{LPCSTR, NTSTATUS},
+ ntstatus::STATUS_SUCCESS,
+ winerror::ERROR_SUCCESS,
+ },
+ um::{
+ libloaderapi::{GetModuleHandleA, GetProcAddress},
+ sysinfoapi::{GetSystemInfo, SYSTEM_INFO},
+ winnt::{
+ KEY_READ, PROCESSOR_ARCHITECTURE_AMD64, REG_SZ, VER_NT_WORKSTATION,
+ VER_SUITE_WH_SERVER, WCHAR,
+ },
+ winreg::{RegOpenKeyExW, RegQueryValueExW, HKEY_LOCAL_MACHINE, LSTATUS},
+ winuser::{GetSystemMetrics, SM_SERVERR2},
+ },
+};
+
+use crate::{Bitness, Info, Type, Version};
+
+#[cfg(target_arch = "x86")]
+type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXA;
+
+#[cfg(not(target_arch = "x86"))]
+type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXW;
+
+pub fn get() -> Info {
+ let (version, edition) = version();
+ Info {
+ os_type: Type::Windows,
+ version,
+ edition,
+ bitness: bitness(),
+ ..Default::default()
+ }
+}
+
+fn version() -> (Version, Option<String>) {
+ match version_info() {
+ None => (Version::Unknown, None),
+ Some(v) => (
+ Version::Semantic(
+ v.dwMajorVersion as u64,
+ v.dwMinorVersion as u64,
+ v.dwBuildNumber as u64,
+ ),
+ product_name().or_else(|| edition(&v)),
+ ),
+ }
+}
+
+#[cfg(target_pointer_width = "64")]
+fn bitness() -> Bitness {
+ // x64 program can only run on x64 Windows.
+ Bitness::X64
+}
+
+#[cfg(target_pointer_width = "32")]
+fn bitness() -> Bitness {
+ use winapi::{
+ shared::{
+ minwindef::{BOOL, FALSE, PBOOL},
+ ntdef::HANDLE,
+ },
+ um::processthreadsapi::GetCurrentProcess,
+ };
+
+ // IsWow64Process is not available on all supported versions of Windows. Use GetModuleHandle to
+ // get a handle to the DLL that contains the function and GetProcAddress to get a pointer to the
+ // function if available.
+ let is_wow_64 = match get_proc_address(b"kernel32\0", b"IsWow64Process\0") {
+ None => return Bitness::Unknown,
+ Some(val) => val,
+ };
+
+ type IsWow64 = unsafe extern "system" fn(HANDLE, PBOOL) -> BOOL;
+ let is_wow_64: IsWow64 = unsafe { mem::transmute(is_wow_64) };
+
+ let mut result = FALSE;
+ if unsafe { is_wow_64(GetCurrentProcess(), &mut result) } == 0 {
+ log::error!("IsWow64Process failed");
+ return Bitness::Unknown;
+ }
+
+ if result == FALSE {
+ Bitness::X32
+ } else {
+ Bitness::X64
+ }
+}
+
+// Calls the Win32 API function RtlGetVersion to get the OS version information:
+// https://msdn.microsoft.com/en-us/library/mt723418(v=vs.85).aspx
+fn version_info() -> Option<OSVERSIONINFOEX> {
+ let rtl_get_version = match get_proc_address(b"ntdll\0", b"RtlGetVersion\0") {
+ None => return None,
+ Some(val) => val,
+ };
+
+ type RtlGetVersion = unsafe extern "system" fn(&mut OSVERSIONINFOEX) -> NTSTATUS;
+ let rtl_get_version: RtlGetVersion = unsafe { mem::transmute(rtl_get_version) };
+
+ let mut info: OSVERSIONINFOEX = unsafe { mem::zeroed() };
+ info.dwOSVersionInfoSize = mem::size_of::<OSVERSIONINFOEX>() as DWORD;
+
+ if unsafe { rtl_get_version(&mut info) } == STATUS_SUCCESS {
+ Some(info)
+ } else {
+ None
+ }
+}
+
+fn product_name() -> Option<String> {
+ const REG_SUCCESS: LSTATUS = ERROR_SUCCESS as LSTATUS;
+
+ let sub_key = to_wide("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
+ let mut key = ptr::null_mut();
+ if unsafe { RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub_key.as_ptr(), 0, KEY_READ, &mut key) }
+ != REG_SUCCESS
+ || key.is_null()
+ {
+ log::error!("RegOpenKeyExW(HKEY_LOCAL_MACHINE, ...) failed");
+ return None;
+ }
+
+ // Get size of the data.
+ let name = to_wide("ProductName");
+ let mut data_type: DWORD = 0;
+ let mut data_size: DWORD = 0;
+ if unsafe {
+ RegQueryValueExW(
+ key,
+ name.as_ptr(),
+ ptr::null_mut(),
+ &mut data_type,
+ ptr::null_mut(),
+ &mut data_size,
+ )
+ } != REG_SUCCESS
+ || data_type != REG_SZ
+ || data_size == 0
+ || data_size % 2 != 0
+ {
+ log::error!("RegQueryValueExW failed");
+ return None;
+ }
+
+ // Get the data.
+ let mut data = vec![0u16; data_size as usize / 2];
+ if unsafe {
+ RegQueryValueExW(
+ key,
+ name.as_ptr(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ data.as_mut_ptr() as LPBYTE,
+ &mut data_size,
+ )
+ } != REG_SUCCESS
+ || data_size as usize != data.len() * 2
+ {
+ return None;
+ }
+
+ // If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been
+ // stored with the proper terminating null characters.
+ match data.last() {
+ Some(0) => {
+ data.pop();
+ }
+ _ => {}
+ }
+
+ Some(
+ OsString::from_wide(data.as_slice())
+ .to_string_lossy()
+ .into_owned(),
+ )
+}
+
+fn to_wide(value: &str) -> Vec<WCHAR> {
+ OsStr::new(value).encode_wide().chain(Some(0)).collect()
+}
+
+// Examines data in the OSVERSIONINFOEX structure to determine the Windows edition:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
+fn edition(version_info: &OSVERSIONINFOEX) -> Option<String> {
+ match (
+ version_info.dwMajorVersion,
+ version_info.dwMinorVersion,
+ version_info.wProductType,
+ ) {
+ // Windows 10.
+ (10, 0, VER_NT_WORKSTATION) => Some("Windows 10"),
+ (10, 0, _) => Some("Windows Server 2016"),
+ // Windows Vista, 7, 8 and 8.1.
+ (6, 3, VER_NT_WORKSTATION) => Some("Windows 8.1"),
+ (6, 3, _) => Some("Windows Server 2012 R2"),
+ (6, 2, VER_NT_WORKSTATION) => Some("Windows 8"),
+ (6, 2, _) => Some("Windows Server 2012"),
+ (6, 1, VER_NT_WORKSTATION) => Some("Windows 7"),
+ (6, 1, _) => Some("Windows Server 2008 R2"),
+ (6, 0, VER_NT_WORKSTATION) => Some("Windows Vista"),
+ (6, 0, _) => Some("Windows Server 2008"),
+ // Windows 2000, Home Server, 2003 Server, 2003 R2 Server, XP and XP Professional x64.
+ (5, 1, _) => Some("Windows XP"),
+ (5, 0, _) => Some("Windows 2000"),
+ (5, 2, _) if unsafe { GetSystemMetrics(SM_SERVERR2) } == 0 => {
+ let mut info: SYSTEM_INFO = unsafe { mem::zeroed() };
+ unsafe { GetSystemInfo(&mut info) };
+
+ if Into::<DWORD>::into(version_info.wSuiteMask) & VER_SUITE_WH_SERVER
+ == VER_SUITE_WH_SERVER
+ {
+ Some("Windows Home Server")
+ } else if version_info.wProductType == VER_NT_WORKSTATION
+ && unsafe { info.u.s().wProcessorArchitecture } == PROCESSOR_ARCHITECTURE_AMD64
+ {
+ Some("Windows XP Professional x64 Edition")
+ } else {
+ Some("Windows Server 2003")
+ }
+ }
+ _ => None,
+ }
+ .map(str::to_string)
+}
+
+fn get_proc_address(module: &[u8], proc: &[u8]) -> Option<FARPROC> {
+ assert!(
+ *module.last().expect("Empty module name") == 0,
+ "Module name should be zero-terminated"
+ );
+ assert!(
+ *proc.last().expect("Empty procedure name") == 0,
+ "Procedure name should be zero-terminated"
+ );
+
+ let handle = unsafe { GetModuleHandleA(module.as_ptr() as LPCSTR) };
+ if handle.is_null() {
+ log::error!(
+ "GetModuleHandleA({}) failed",
+ String::from_utf8_lossy(module)
+ );
+ return None;
+ }
+
+ unsafe { Some(GetProcAddress(handle, proc.as_ptr() as LPCSTR)) }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::{assert_eq, assert_ne};
+
+ #[test]
+ fn version() {
+ let info = get();
+ assert_eq!(Type::Windows, info.os_type());
+ }
+
+ #[test]
+ fn get_version_info() {
+ let version = version_info();
+ assert!(version.is_some());
+ }
+
+ #[test]
+ fn get_edition() {
+ let test_data = [
+ (10, 0, VER_NT_WORKSTATION, "Windows 10"),
+ (10, 0, 0, "Windows Server 2016"),
+ (6, 3, VER_NT_WORKSTATION, "Windows 8.1"),
+ (6, 3, 0, "Windows Server 2012 R2"),
+ (6, 2, VER_NT_WORKSTATION, "Windows 8"),
+ (6, 2, 0, "Windows Server 2012"),
+ (6, 1, VER_NT_WORKSTATION, "Windows 7"),
+ (6, 1, 0, "Windows Server 2008 R2"),
+ (6, 0, VER_NT_WORKSTATION, "Windows Vista"),
+ (6, 0, 0, "Windows Server 2008"),
+ (5, 1, 0, "Windows XP"),
+ (5, 1, 1, "Windows XP"),
+ (5, 1, 100, "Windows XP"),
+ (5, 0, 0, "Windows 2000"),
+ (5, 0, 1, "Windows 2000"),
+ (5, 0, 100, "Windows 2000"),
+ ];
+
+ let mut info = version_info().unwrap();
+
+ for &(major, minor, product_type, expected_edition) in &test_data {
+ info.dwMajorVersion = major;
+ info.dwMinorVersion = minor;
+ info.wProductType = product_type;
+
+ let edition = edition(&info).unwrap();
+ assert_eq!(edition, expected_edition);
+ }
+ }
+
+ #[test]
+ fn get_bitness() {
+ let b = bitness();
+ assert_ne!(b, Bitness::Unknown);
+ }
+
+ #[test]
+ #[should_panic(expected = "Empty module name")]
+ fn empty_module_name() {
+ get_proc_address(b"", b"RtlGetVersion\0");
+ }
+
+ #[test]
+ #[should_panic(expected = "Module name should be zero-terminated")]
+ fn non_zero_terminated_module_name() {
+ get_proc_address(b"ntdll", b"RtlGetVersion\0");
+ }
+
+ #[test]
+ #[should_panic(expected = "Empty procedure name")]
+ fn empty_proc_name() {
+ get_proc_address(b"ntdll\0", b"");
+ }
+
+ #[test]
+ #[should_panic(expected = "Procedure name should be zero-terminated")]
+ fn non_zero_terminated_proc_name() {
+ get_proc_address(b"ntdll\0", b"RtlGetVersion");
+ }
+
+ #[test]
+ fn proc_address() {
+ let address = get_proc_address(b"ntdll\0", b"RtlGetVersion\0");
+ assert!(address.is_some());
+ }
+
+ #[test]
+ fn get_product_name() {
+ let edition = product_name().expect("edition() failed");
+ assert!(!edition.is_empty());
+ }
+
+ #[test]
+ fn to_wide_str() {
+ let data = [
+ ("", [0x0000].as_ref()),
+ ("U", &[0x0055, 0x0000]),
+ ("你好", &[0x4F60, 0x597D, 0x0000]),
+ ];
+
+ for (s, expected) in &data {
+ let wide = to_wide(s);
+ assert_eq!(&wide, expected);
+ }
+ }
+}