summaryrefslogtreecommitdiffstats
path: root/vendor/os_info
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/os_info')
-rw-r--r--vendor/os_info/.cargo-checksum.json1
-rw-r--r--vendor/os_info/Cargo.lock158
-rw-r--r--vendor/os_info/Cargo.toml65
-rw-r--r--vendor/os_info/LICENSE21
-rw-r--r--vendor/os_info/README.md128
-rw-r--r--vendor/os_info/examples/print_version.rs14
-rw-r--r--vendor/os_info/src/android/mod.rs23
-rw-r--r--vendor/os_info/src/architecture.rs32
-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.rs343
-rw-r--r--vendor/os_info/src/lib.rs119
-rw-r--r--vendor/os_info/src/linux/file_release.rs574
-rw-r--r--vendor/os_info/src/linux/lsb_release.rs518
-rw-r--r--vendor/os_info/src/linux/mod.rs62
-rw-r--r--vendor/os_info/src/linux/tests/Alpaquita/etc/os-release8
-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/Arch/etc/os-release11
-rw-r--r--vendor/os_info/src/linux/tests/ArchARM/etc/os-release11
-rw-r--r--vendor/os_info/src/linux/tests/Artix/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/Debian_11/etc/os-release9
-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/OpenCloudOS/etc/os-release9
-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/linux/tests/openEuler/etc/os-release6
-rw-r--r--vendor/os_info/src/macos/mod.rs107
-rw-r--r--vendor/os_info/src/matcher.rs148
-rw-r--r--vendor/os_info/src/netbsd/mod.rs36
-rw-r--r--vendor/os_info/src/openbsd/mod.rs36
-rw-r--r--vendor/os_info/src/os_type.rs176
-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.rs387
-rw-r--r--vendor/os_info/tests/basic.rs4
-rw-r--r--vendor/os_info/tests/md_doc.rs3
64 files changed, 3817 insertions, 0 deletions
diff --git a/vendor/os_info/.cargo-checksum.json b/vendor/os_info/.cargo-checksum.json
new file mode 100644
index 0000000..db33757
--- /dev/null
+++ b/vendor/os_info/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{},"package":"006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e"} \ No newline at end of file
diff --git a/vendor/os_info/Cargo.lock b/vendor/os_info/Cargo.lock
new file mode 100644
index 0000000..2a9b409
--- /dev/null
+++ b/vendor/os_info/Cargo.lock
@@ -0,0 +1,158 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "ctor"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "diff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "os_info"
+version = "3.7.0"
+dependencies = [
+ "doc-comment",
+ "log",
+ "pretty_assertions",
+ "serde",
+ "winapi",
+]
+
+[[package]]
+name = "output_vt100"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "pretty_assertions"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563"
+dependencies = [
+ "ansi_term",
+ "ctor",
+ "diff",
+ "output_vt100",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/os_info/Cargo.toml b/vendor/os_info/Cargo.toml
new file mode 100644
index 0000000..52a062f
--- /dev/null
+++ b/vendor/os_info/Cargo.toml
@@ -0,0 +1,65 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.60"
+name = "os_info"
+version = "3.7.0"
+authors = [
+ "Jan Schulte <hello@unexpected-co.de>",
+ "Stanislav Tkach <stanislav.tkach@gmail.com>",
+]
+description = "Detect the operating system type and version."
+homepage = "https://github.com/stanislav-tkach/os_info"
+documentation = "https://docs.rs/os_info"
+readme = "README.md"
+keywords = [
+ "os",
+ "os_type",
+ "os_version",
+ "os_info",
+]
+categories = ["os"]
+license = "MIT"
+repository = "https://github.com/stanislav-tkach/os_info"
+
+[dependencies.log]
+version = "0.4.5"
+
+[dependencies.serde]
+version = "1"
+features = ["derive"]
+optional = true
+
+[dev-dependencies.doc-comment]
+version = "0.3.1"
+
+[dev-dependencies.pretty_assertions]
+version = "1"
+
+[features]
+default = ["serde"]
+
+[target."cfg(windows)".dependencies.winapi]
+version = "0.3.8"
+features = [
+ "minwindef",
+ "ntdef",
+ "ntstatus",
+ "sysinfoapi",
+ "winnt",
+ "winuser",
+ "libloaderapi",
+ "processthreadsapi",
+ "winerror",
+ "winreg",
+]
diff --git a/vendor/os_info/LICENSE b/vendor/os_info/LICENSE
new file mode 100644
index 0000000..68e1407
--- /dev/null
+++ b/vendor/os_info/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Stanislav Tkach
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/os_info/README.md b/vendor/os_info/README.md
new file mode 100644
index 0000000..6e34f2d
--- /dev/null
+++ b/vendor/os_info/README.md
@@ -0,0 +1,128 @@
+# os_info
+
+**Status:**
+[![CI](https://github.com/stanislav-tkach/os_info/workflows/CI/badge.svg)](https://github.com/stanislav-tkach/os_info/actions)
+[![Coverage](https://codecov.io/gh/stanislav-tkach/os_info/branch/master/graph/badge.svg)](https://codecov.io/gh/stanislav-tkach/os_info)
+[![Dependency status](https://deps.rs/repo/github/stanislav-tkach/os_info/status.svg)](https://deps.rs/repo/github/stanislav-tkach/os_info)
+
+**Project info:**
+[![Docs.rs](https://docs.rs/os_info/badge.svg)](https://docs.rs/os_info)
+[![Latest version](https://img.shields.io/crates/v/os_info.svg)](https://crates.io/crates/os_info)
+[![License](https://img.shields.io/github/license/stanislav-tkach/os_info.svg)](https://github.com/stanislav-tkach/os_info/blob/master/LICENSE)
+
+**Project details:**
+[![LoC](https://tokei.rs/b1/github/stanislav-tkach/os_info)](https://github.com/stanislav-tkach/os_info)
+![Rust 1.60+ required](https://img.shields.io/badge/rust-1.41+-blue.svg?label=Required%20Rust)
+
+## Overview
+
+This project consists of two parts: the library that can be used to detect the
+operating system type (including version and bitness) and the command line tool
+that uses the library.
+
+### Library (`os_info`)
+
+#### `os_info` usage
+
+To use this crate, add `os_info` as a dependency to your project's Cargo.toml:
+
+```toml
+[dependencies]
+os_info = "3"
+```
+
+This project has `serde` as an optional dependency, so if you don't need it, then
+you can speed up compilation disabling it:
+
+```toml
+[dependencies]
+os_info = { version = "3", default-features = false }
+```
+
+#### Example
+
+```rust
+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!("Bitness: {}", info.bitness());
+println!("Architecture: {}", info.architecture());
+```
+
+### Command line tool (`os_info_cli`)
+
+A simple wrapper around the `os_info` library.
+
+#### Installation
+
+This tool can be installed using the following cargo command:
+
+```console
+cargo install os_info_cli
+```
+
+#### `os_info_cli` usage
+
+Despite being named `os_info_cli` during installation, it is actually named
+`os_info`. You can use the `--help` flag to see available options:
+
+```console
+os_info --help
+```
+
+## Supported operating systems
+
+Right now, the following operating system types can be returned:
+
+- Alpaquita Linux
+- Alpine Linux
+- Amazon Linux AMI
+- Android
+- Arch Linux
+- Artix Linux
+- CentOS
+- Debian
+- DragonFly BSD
+- Emscripten
+- EndeavourOS
+- Fedora
+- FreeBSD
+- Garuda Linux
+- Gentoo Linux
+- HardenedBSD
+- Illumos
+- Linux
+- macOS (Mac OS X or OS X)
+- Manjaro
+- Mariner
+- MidnightBSD
+- Mint
+- NetBSD
+- NixOS
+- OpenBSD
+- openSUSE
+- Oracle Linux
+- Pop!_OS
+- Raspberry Pi OS
+- Red Hat Linux
+- Red Hat Enterprise Linux
+- Redox
+- Solus
+- SUSE Linux Enterprise Server
+- Ubuntu
+- Unknown
+- Windows
+
+If you need support for more OS types, I am looking forward to your Pull Request.
+
+## License
+
+`os_info` is licensed under the MIT license. See [LICENSE] for the details.
+
+[lsb_release]: http://refspecs.linuxbase.org/LSB_2.0.1/LSB-PDA/LSB-PDA/lsbrelease.html
+[LICENSE]: https://github.com/stanislav-tkach/os_info/blob/master/LICENSE
diff --git a/vendor/os_info/examples/print_version.rs b/vendor/os_info/examples/print_version.rs
new file mode 100644
index 0000000..dc5bbad
--- /dev/null
+++ b/vendor/os_info/examples/print_version.rs
@@ -0,0 +1,14 @@
+fn main() {
+ 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());
+ println!("Architecture: {:?}", info.architecture());
+}
diff --git a/vendor/os_info/src/android/mod.rs b/vendor/os_info/src/android/mod.rs
new file mode 100644
index 0000000..51c99ba
--- /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/architecture.rs b/vendor/os_info/src/architecture.rs
new file mode 100644
index 0000000..d6de08b
--- /dev/null
+++ b/vendor/os_info/src/architecture.rs
@@ -0,0 +1,32 @@
+use std::process::Command;
+
+use log::error;
+
+pub fn get() -> Option<String> {
+ Command::new("uname")
+ .arg("-m")
+ .output()
+ .map_err(|e| {
+ error!("Cannot invoke 'uname` to get architecture type: {:?}", 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 = get().expect("uname failed");
+ assert!(!val.is_empty());
+ }
+}
diff --git a/vendor/os_info/src/bitness.rs b/vendor/os_info/src/bitness.rs
new file mode 100644
index 0000000..dba7e1c
--- /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 0000000..63fe0e7
--- /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 0000000..36be377
--- /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 0000000..09c8dbe
--- /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 0000000..1f23771
--- /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 0000000..91e6cc3
--- /dev/null
+++ b/vendor/os_info/src/info.rs
@@ -0,0 +1,343 @@
+// 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 codename.
+ 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,
+ /// Processor architecture.
+ pub(crate) architecture: Option<String>,
+}
+
+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());
+ /// assert_eq!(None, info.architecture());
+ /// ```
+ pub fn unknown() -> Self {
+ Self {
+ os_type: Type::Unknown,
+ version: Version::Unknown,
+ edition: None,
+ codename: None,
+ bitness: Bitness::Unknown,
+ architecture: None,
+ }
+ }
+
+ /// 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());
+ /// assert_eq!(None, info.architecture());
+ /// ```
+ 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
+ }
+
+ /// Returns operating system architecture.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use os_info::Info;
+ ///
+ /// let info = Info::unknown();
+ /// assert_eq!(None, info.architecture());
+ pub fn architecture(&self) -> Option<&str> {
+ self.architecture.as_ref().map(String::as_ref)
+ }
+}
+
+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());
+ assert_eq!(None, info.architecture());
+ }
+
+ #[test]
+ fn with_type() {
+ let types = [
+ Type::Redox,
+ Type::Alpaquita,
+ Type::Alpine,
+ Type::Amazon,
+ Type::Android,
+ Type::Arch,
+ Type::Artix,
+ Type::CentOS,
+ Type::Debian,
+ Type::Emscripten,
+ Type::EndeavourOS,
+ Type::Fedora,
+ Type::Gentoo,
+ Type::Linux,
+ Type::Macos,
+ Type::Manjaro,
+ Type::Mariner,
+ Type::NixOS,
+ Type::OpenCloudOS,
+ Type::openEuler,
+ 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::Artix,
+ version: Version::Rolling(None),
+ ..Default::default()
+ },
+ "Artix 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,
+ architecture: Some("architecture".to_owned()),
+ },
+ "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 0000000..83c7f38
--- /dev/null
+++ b/vendor/os_info/src/lib.rs
@@ -0,0 +1,119 @@
+//! `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;
+
+#[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
+mod architecture;
+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());
+/// println!("Architecture: {:?}", info.architecture());
+/// ```
+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 0000000..e9cb6c3
--- /dev/null
+++ b/vendor/os_info/src/linux/file_release.rs
@@ -0,0 +1,574 @@
+// 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
+ "alpaquita" => Some(Type::Alpaquita),
+ "alpine" => Some(Type::Alpine),
+ "amzn" => Some(Type::Amazon),
+ //"antergos" => Antergos
+ //"aosc" => AOSC
+ "arch" => Some(Type::Arch),
+ "archarm" => Some(Type::Arch),
+ "artix" => Some(Type::Artix),
+ "centos" => Some(Type::CentOS),
+ //"clear-linux-os" => ClearLinuxOS
+ //"clearos" => ClearOS
+ //"coreos"
+ //"cumulus-linux" => Cumulus
+ "debian" => Some(Type::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),
+ "opencloudos" => Some(Type::OpenCloudOS),
+ "openEuler" => Some(Type::openEuler),
+ "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 alpaquita_os_release() {
+ let root = "src/linux/tests/Alpaquita";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Alpaquita);
+ assert_eq!(info.version, Version::Semantic(23, 0, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[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 arch_os_release() {
+ let root = "src/linux/tests/Arch";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Arch);
+ assert_eq!(info.version, Version::Unknown);
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn archarm_os_release() {
+ let root = "src/linux/tests/ArchARM";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Arch);
+ assert_eq!(info.version, Version::Unknown);
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn artix_os_release() {
+ let root = "src/linux/tests/Artix";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Artix);
+ assert_eq!(info.version, Version::Unknown);
+ 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 debian_11_os_release() {
+ let root = "src/linux/tests/Debian_11";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::Debian);
+ assert_eq!(info.version, Version::Semantic(11, 0, 0));
+ 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 opencloudos_os_release() {
+ let root = "src/linux/tests/OpenCloudOS";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::OpenCloudOS);
+ assert_eq!(info.version, Version::Semantic(8, 6, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, None);
+ }
+
+ #[test]
+ fn openeuler_os_release() {
+ let root = "src/linux/tests/openEuler";
+
+ let info = retrieve(&DISTRIBUTIONS, root).unwrap();
+ assert_eq!(info.os_type(), Type::openEuler);
+ assert_eq!(info.version, Version::Semantic(22, 3, 0));
+ assert_eq!(info.edition, None);
+ assert_eq!(info.codename, 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 0000000..a494fce
--- /dev/null
+++ b/vendor/os_info/src/linux/lsb_release.rs
@@ -0,0 +1,518 @@
+// 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("Alpaquita") => Type::Alpaquita,
+ Some("Amazon") | Some("AmazonAMI") => Type::Amazon,
+ Some("Arch") => Type::Arch,
+ Some("Artix") => Type::Artix,
+ 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("MaboxLinux") => Type::Mabox,
+ Some("ManjaroLinux") => Type::Manjaro,
+ Some("Mariner") => Type::Mariner,
+ Some("NixOS") => Type::NixOS,
+ Some("OpenCloudOS") => Type::OpenCloudOS,
+ Some("openEuler") => Type::openEuler,
+ 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 alpaquita() {
+ let parse_results = parse(alpaquita_file());
+ assert_eq!(parse_results.distribution, Some("Alpaquita".to_string()));
+ assert_eq!(parse_results.version, Some("23".to_string()));
+ assert_eq!(parse_results.codename, None);
+ }
+
+ #[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 artix() {
+ let parse_results = parse(artix_file());
+ assert_eq!(parse_results.distribution, Some("Artix".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 alpaquita_file() -> &'static str {
+ "\nDistributor ID: Alpaquita\n\
+ Description: BellSoft Alpaquita Linux Stream 23 (musl)\n\
+ Release: 23\n\
+ Codename: n/a"
+ }
+
+ 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 artix_file() -> &'static str {
+ "\nLSB Version: n/a\n\
+ Distributor ID: Artix\n\
+ Description: Artix 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 0000000..ac5c8cc
--- /dev/null
+++ b/vendor/os_info/src/linux/mod.rs
@@ -0,0 +1,62 @@
+mod file_release;
+mod lsb_release;
+
+use log::trace;
+
+use crate::{architecture, 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();
+ info.architecture = architecture::get();
+
+ trace!("Returning {:?}", info);
+ info
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn os_type() {
+ let version = current_platform();
+ match version.os_type() {
+ Type::Alpaquita
+ | Type::Alpine
+ | Type::Amazon
+ | Type::Arch
+ | Type::Artix
+ | Type::CentOS
+ | Type::Debian
+ | Type::EndeavourOS
+ | Type::Fedora
+ | Type::Garuda
+ | Type::Gentoo
+ | Type::Linux
+ | Type::Mabox
+ | Type::Manjaro
+ | Type::Mariner
+ | Type::NixOS
+ | Type::OpenCloudOS
+ | Type::openEuler
+ | 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/Alpaquita/etc/os-release b/vendor/os_info/src/linux/tests/Alpaquita/etc/os-release
new file mode 100644
index 0000000..4c47ccd
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Alpaquita/etc/os-release
@@ -0,0 +1,8 @@
+NAME="BellSoft Alpaquita Linux Stream"
+ID=alpaquita
+ID_LIKE=alpine
+VERSION_ID=23
+PRETTY_NAME="BellSoft Alpaquita Linux Stream 23 (musl)"
+HOME_URL="https://bell-sw.com/"
+BUG_REPORT_URL="https://bell-sw.com/support/"
+LIBC_TYPE=musl
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 0000000..8656231
--- /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 0000000..c2e6bc6
--- /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 0000000..b2b1a07
--- /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 0000000..07a4507
--- /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/Arch/etc/os-release b/vendor/os_info/src/linux/tests/Arch/etc/os-release
new file mode 100644
index 0000000..8662a54
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Arch/etc/os-release
@@ -0,0 +1,11 @@
+NAME="Arch Linux"
+PRETTY_NAME="Arch Linux"
+ID=arch
+BUILD_ID=rolling
+ANSI_COLOR="38;2;23;147;209"
+HOME_URL="https://archlinux.org/"
+DOCUMENTATION_URL="https://wiki.archlinux.org/"
+SUPPORT_URL="https://bbs.archlinux.org/"
+BUG_REPORT_URL="https://bugs.archlinux.org/"
+PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
+LOGO=archlinux-logo
diff --git a/vendor/os_info/src/linux/tests/ArchARM/etc/os-release b/vendor/os_info/src/linux/tests/ArchARM/etc/os-release
new file mode 100644
index 0000000..6218b0e
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/ArchARM/etc/os-release
@@ -0,0 +1,11 @@
+NAME="Arch Linux ARM"
+PRETTY_NAME="Arch Linux ARM"
+ID=archarm
+ID_LIKE=arch
+BUILD_ID=rolling
+ANSI_COLOR="38;2;23;147;209"
+HOME_URL="https://archlinuxarm.org/"
+DOCUMENTATION_URL="https://archlinuxarm.org/wiki"
+SUPPORT_URL="https://archlinuxarm.org/forum"
+BUG_REPORT_URL="https://github.com/archlinuxarm/PKGBUILDs/issues"
+LOGO=archlinux-logo
diff --git a/vendor/os_info/src/linux/tests/Artix/etc/os-release b/vendor/os_info/src/linux/tests/Artix/etc/os-release
new file mode 100644
index 0000000..26279ce
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Artix/etc/os-release
@@ -0,0 +1,9 @@
+NAME="Artix Linux"
+PRETTY_NAME="Artix Linux"
+ID=artix
+BUILD_ID=rolling
+ANSI_COLOR="38;2;23;147;209"
+HOME_URL="https://artixlinux.org/"
+DOCUMENTATION_URL="https://wiki.artixlinux.org/"
+SUPPORT_URL="https://forum.artixlinux.org/"
+BUG_REPORT_URL="https://gitea.artixlinux.org/artix"
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 0000000..359ef00
--- /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 0000000..c276e3a
--- /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 0000000..8948e12
--- /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 0000000..e6b865b
--- /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/Debian_11/etc/os-release b/vendor/os_info/src/linux/tests/Debian_11/etc/os-release
new file mode 100644
index 0000000..611cf74
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/Debian_11/etc/os-release
@@ -0,0 +1,9 @@
+PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
+NAME="Debian GNU/Linux"
+VERSION_ID="11"
+VERSION="11 (bullseye)"
+VERSION_CODENAME=bullseye
+ID=debian
+HOME_URL="https://www.debian.org/"
+SUPPORT_URL="https://www.debian.org/support"
+BUG_REPORT_URL="https://bugs.debian.org/"
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 0000000..f2641f4
--- /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 0000000..234ecf1
--- /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 0000000..9178d6d
--- /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 0000000..adc0115
--- /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 0000000..f4bceb4
--- /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 0000000..d64fd53
--- /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 0000000..825d928
--- /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 0000000..b93cf4d
--- /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/OpenCloudOS/etc/os-release b/vendor/os_info/src/linux/tests/OpenCloudOS/etc/os-release
new file mode 100644
index 0000000..4bc4580
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/OpenCloudOS/etc/os-release
@@ -0,0 +1,9 @@
+NAME="OpenCloudOS"
+VERSION="8.6"
+ID="opencloudos"
+ID_LIKE="rhel fedora centos"
+VERSION_ID="8.6"
+PLATFORM_ID="platform:oc8"
+PRETTY_NAME="OpenCloudOS 8.6"
+ANSI_COLOR="0;31"
+CPE_NAME="cpe:/o:opencloudos:opencloudos:8" \ No newline at end of file
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 0000000..1594788
--- /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 0000000..994041e
--- /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 0000000..ff4da1d
--- /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 0000000..ec038b1
--- /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 0000000..1d5515b
--- /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 0000000..e69de29
--- /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 0000000..2de3f28
--- /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 0000000..54fafb5
--- /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 0000000..2369e58
--- /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 0000000..92258e6
--- /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/linux/tests/openEuler/etc/os-release b/vendor/os_info/src/linux/tests/openEuler/etc/os-release
new file mode 100644
index 0000000..bd72dd8
--- /dev/null
+++ b/vendor/os_info/src/linux/tests/openEuler/etc/os-release
@@ -0,0 +1,6 @@
+NAME="openEuler"
+VERSION="22.03 LTS"
+ID="openEuler"
+VERSION_ID="22.03"
+PRETTY_NAME="openEuler 22.03 LTS"
+ANSI_COLOR="0;31" \ No newline at end of file
diff --git a/vendor/os_info/src/macos/mod.rs b/vendor/os_info/src/macos/mod.rs
new file mode 100644
index 0000000..aef79d2
--- /dev/null
+++ b/vendor/os_info/src/macos/mod.rs
@@ -0,0 +1,107 @@
+use std::process::Command;
+
+use log::{trace, warn};
+
+use crate::{architecture, 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(),
+ architecture: architecture::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 0000000..fcc31bc
--- /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 0000000..7031820
--- /dev/null
+++ b/vendor/os_info/src/netbsd/mod.rs
@@ -0,0 +1,36 @@
+use std::process::Command;
+
+use log::{error, trace};
+
+use crate::{architecture, 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(),
+ architecture: architecture::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 0000000..c9eeee4
--- /dev/null
+++ b/vendor/os_info/src/openbsd/mod.rs
@@ -0,0 +1,36 @@
+use std::process::Command;
+
+use log::{error, trace};
+
+use crate::{architecture, 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(),
+ architecture: architecture::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 0000000..6d78f58
--- /dev/null
+++ b/vendor/os_info/src/os_type.rs
@@ -0,0 +1,176 @@
+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 {
+ /// Alpaquita Linux (<https://bell-sw.com/alpaquita-linux/>).
+ Alpaquita,
+ /// 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,
+ /// Artix Linux (<https://en.wikipedia.org/wiki/Artix_Linux>).
+ Artix,
+ /// 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,
+ /// Mabox (<https://maboxlinux.org/>).
+ Mabox,
+ /// 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,
+ /// OpenCloudOS (<https://www.opencloudos.org>).
+ OpenCloudOS,
+ /// openEuler (<https://en.wikipedia.org/wiki/EulerOS>).
+ openEuler,
+ /// 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::Alpaquita => write!(f, "Alpaquita Linux"),
+ Type::Alpine => write!(f, "Alpine Linux"),
+ Type::Amazon => write!(f, "Amazon Linux AMI"),
+ Type::Arch => write!(f, "Arch Linux"),
+ Type::Artix => write!(f, "Artix 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::Alpaquita, "Alpaquita Linux"),
+ (Type::Alpine, "Alpine Linux"),
+ (Type::Amazon, "Amazon Linux AMI"),
+ (Type::Android, "Android"),
+ (Type::Arch, "Arch Linux"),
+ (Type::Artix, "Artix 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 0000000..1efd591
--- /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 0000000..f4417e8
--- /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 0000000..fbebe21
--- /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 0000000..578464c
--- /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 0000000..4e57d4a
--- /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 0000000..dea5ba2
--- /dev/null
+++ b/vendor/os_info/src/windows/winapi.rs
@@ -0,0 +1,387 @@
+// 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(&v).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(info: &OSVERSIONINFOEX) -> 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;
+ }
+
+ let is_win_11 = info.dwMajorVersion == 10 && info.dwBuildNumber >= 22000;
+
+ // Get size of the data.
+ let name = to_wide(if is_win_11 {
+ "EditionID"
+ } else {
+ "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();
+ }
+ _ => {}
+ }
+
+ let value = OsString::from_wide(data.as_slice())
+ .to_string_lossy()
+ .into_owned();
+
+ if is_win_11 {
+ Some(format!("Windows 11 {}", value))
+ } else {
+ Some(value)
+ }
+}
+
+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) => {
+ if version_info.dwBuildNumber >= 22000 {
+ Some("Windows 11")
+ } else {
+ 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, 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 version = version_info().expect("version_info() failed");
+ let edition = product_name(&version).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);
+ }
+ }
+}
diff --git a/vendor/os_info/tests/basic.rs b/vendor/os_info/tests/basic.rs
new file mode 100644
index 0000000..c48565f
--- /dev/null
+++ b/vendor/os_info/tests/basic.rs
@@ -0,0 +1,4 @@
+#[test]
+fn get() {
+ let _ = os_info::get();
+}
diff --git a/vendor/os_info/tests/md_doc.rs b/vendor/os_info/tests/md_doc.rs
new file mode 100644
index 0000000..7347324
--- /dev/null
+++ b/vendor/os_info/tests/md_doc.rs
@@ -0,0 +1,3 @@
+// spell-checker:ignore doctest
+
+doc_comment::doctest!("../README.md");