From 314b535e337459068e87b710a6ccfe51417479a8 Mon Sep 17 00:00:00 2001 From: JasonHonor Date: Fri, 21 Apr 2023 14:56:19 +0800 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c9b13af396eecc8118f438b36db140bc4565d6e2 Merge: 34c12c7 9d32433 Author: Stanislav Tkach Date: Sun Mar 26 10:05:09 2023 +0200 Merge pull request #345 from Killavus/add_architecture_to_windows_info feat: Add architecture information for Windows targets commit 9d32433ac3b7943b97ff6bc14e7cd71f24716b0a Author: Killavus Date: Wed Mar 22 03:12:35 2023 +0100 add architecture information for windows platforms commit 34c12c79ab894de320a575b0be0e3e1fd8d3081b Merge: 755ae48 4e92fef Author: Stanislav Tkach Date: Mon Mar 20 18:57:59 2023 +0100 Merge pull request #341 from poliorcetics/winapi-to-windows-sys deps: Move from winapi to windows-sys commit 755ae488dfc5d34a424a998bdb5c947e82bc2976 Merge: 5fbb59c 4601e95 Author: Stanislav Tkach Date: Mon Mar 20 16:25:37 2023 +0100 Merge pull request #344 from stanislav-tkach/release-3-7-0 Release the 3.7.0 version commit 4e92fef79c425dd368552e50c347ab8bbced3a0d Author: Alexis (Poliorcetics) Bourget Date: Mon Mar 6 18:23:53 2023 +0100 deps: Move from winapi to windows-sys `winapi` is in maintenance mode and the new blessed way to access Windows APIs are the `windows` and `windows-sys` crates. I don't think any types of `winapi` were exposed in the public API so I used `windows-sys` since it has much faster compile times. commit 4601e95b1308b1216d040fd377dca9a52584ec94 Author: Stanislav Tkach Date: Sun Mar 19 20:15:29 2023 +0100 Update the changelog commit 2b925cff76dff3ddc644ef94aa34eb607667699f Merge: 9bf66a4 5fbb59c Author: Stanislav Tkach Date: Sun Mar 19 18:05:14 2023 +0100 Merge branch 'master' into release-3-7-0 commit 5fbb59cca1193538697cf2c21707aed3b7134404 Merge: 4114330 24fcc88 Author: Stanislav Tkach Date: Sun Mar 19 18:04:25 2023 +0100 Merge pull request #340 from kholmanskikh/add-alpaquita-linux Add Alpaquita Linux commit 9bf66a4cedc7e56ab94e5d72ffcc4382007fb0ce Author: Stanislav Tkach Date: Sun Mar 19 17:09:16 2023 +0100 Release the 3.7.0 version commit 411433032b56b9cb598cf1e6642ccc323728155d Merge: 9ccebce 4fa38e4 Author: Stanislav Tkach Date: Wed Mar 15 19:58:36 2023 +0100 Merge pull request #343 from stanislav-tkach/dependabot/cargo/predicates-3 Update predicates requirement from 2 to 3 commit 4fa38e47296d787f7e1ae5f7ee7bde0b6475eee1 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed Mar 15 14:59:15 2023 +0000 Update predicates requirement from 2 to 3 Updates the requirements on [predicates](https://github.com/assert-rs/predicates-rs) to permit the latest version. - [Release notes](https://github.com/assert-rs/predicates-rs/releases) - [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/assert-rs/predicates-rs/compare/v2.0.0...v3.0.0) --- updated-dependencies: - dependency-name: predicates dependency-type: direct:production ... Signed-off-by: dependabot[bot] commit 9ccebce50e07172a03311d7e6eda8249fe92b77e Merge: 39c38f3 f156026 Author: Stanislav Tkach Date: Mon Mar 13 11:42:02 2023 +0100 Merge pull request #342 from codybloemhard/master Add support for Artix Linux commit f1560261074a1910835cbc7961e0fd3a11572fee Author: Cody Bloemhard Date: Fri Mar 10 15:26:59 2023 +0100 Add support for Artix Linux commit 24fcc88bed7e5b489c73722f655f15b0809f8095 Author: Stanislav Kholmanskikh Date: Wed Mar 1 17:00:43 2023 +0300 Add Alpaquita Linux The distro does not ship LSB utils, so the LSB code path was tested with a manually built version of lsb-release-minimal from https://salsa.debian.org/gioele/lsb-release-minimal commit 39c38f3cb80eaa519eb3b7a99e478cc8ffc7e6f2 Merge: b9eef20 b0ec30a Author: Stanislav Tkach Date: Mon Feb 27 23:33:07 2023 +0100 Merge pull request #338 from Arto-O/master Add support for Mabox, resolves #337 commit b9eef209c7687fee53a6bd5986713243af54a54c Merge: 7011ce4 3f303c8 Author: Stanislav Tkach Date: Mon Feb 20 01:07:20 2023 +0100 Merge pull request #336 from rbas/335-issue-add-processor-architecture-informations 335 issue add processor architecture informations commit b0ec30ac6acea2c0d049b26eafd56c71231b9131 Author: Arto-O Date: Sat Feb 18 15:09:25 2023 -0800 Add support for Mabox commit 3f303c8dcb6e0c6e3f75d2696bf8c575f4b94182 Author: Martin Voldřich Date: Mon Feb 13 17:55:20 2023 +0100 Fixing doc string commit 1d4b2600733bf5ce3679bb3f975f5549cafe90d8 Author: Martin Voldřich Date: Mon Feb 13 17:54:49 2023 +0100 Adding information about architecture commit 7011ce412b21dbc8a0315bcaa19efca386af7ebc Merge: b12491e 5377003 Author: Stanislav Tkach Date: Mon Jan 30 19:12:46 2023 +0100 Merge pull request #332 from stanislav-tkach/release-3-6-0 Release the 3.6.0 version commit 5377003725784cd6eaf5e437d322bac8c4fb2849 Author: Stanislav Tkach Date: Sun Jan 29 23:31:53 2023 +0100 More fixes commit 7fc22cbdc2872bcbf9a243e247d8dab8c3e079fd Author: Stanislav Tkach Date: Sun Jan 29 23:13:32 2023 +0100 Fix clippy warnings commit b377859088611f621b1eccdaf41ce0d93008bae4 Author: Stanislav Tkach Date: Sun Jan 29 23:04:53 2023 +0100 Release the 3.6.0 version commit b12491ec23b44664e08716b6c1cc9b848b0a6a0b Merge: 4e1cf37 3416fb4 Author: Stanislav Tkach Date: Mon Jan 23 13:45:21 2023 +0100 Merge pull request #331 from meop/master add os-release match for Arch and Debian ARM commit 3416fb4914f029589303201c57cd667e95a7574e Author: Marshall Porter Date: Fri Jan 20 09:10:43 2023 -0800 add os-release match for Arch and Debian ARM commit 4e1cf372119eb6c63ed4149bd50ff6348772db8f Merge: 5e42e34 c8f05e2 Author: Stanislav Tkach Date: Sat Jan 7 00:14:29 2023 +0100 Merge pull request #330 from stanislav-tkach/fix-fmt-and-spellcheck Fix formattin and add new words to the spellchecker dictionary commit c8f05e2eeea22b4225346807b1c01cf965bc702d Author: Stanislav Tkach Date: Fri Jan 6 22:30:06 2023 +0100 Fix formattin and add new words to the spellchecker dictionary commit 5e42e345dcdb1a173336a111f74c92c1b317b3c2 Merge: 75ef20a eb9977d Author: Stanislav Tkach Date: Sun Jan 1 22:20:08 2023 +0100 Merge pull request #328 from leavelet/master Add openEuler and OpenCloudOS support commit eb9977d9e5ccc870669bec99ca3954dcfc42209e Author: leavelet Date: Sat Dec 31 16:49:10 2022 +0800 Add openEuler and OpenCloudOS tests commit faad546d00698cc027a6d39f40d989583f419ea4 Author: leavelet Date: Sat Dec 31 14:25:52 2022 +0800 Add openEuler and OpenCloudOS support commit 75ef20a0f6a6fe333267b83689a0c5b82be7e678 Merge: 3c2f3a3 e36d819 Author: Stanislav Tkach Date: Sun Dec 25 01:14:54 2022 +0200 Merge pull request #327 from stanislav-tkach/min-rust-version-in-toml Set minimal supported Rust version in the Cargo.toml file commit e36d819d0583ec6bbea3a1f4b98564e278bf52d2 Author: Stanislav Tkach Date: Fri Dec 23 00:43:26 2022 +0100 fix commit 7e7619ba06abf7c050598fa156de17874866dddf Author: Stanislav Tkach Date: Thu Dec 22 15:04:55 2022 +0100 Min version 1.60 commit d337860b6cfc27f06f1f0b6422e80b05e62df2f9 Merge: bbcd770 3c2f3a3 Author: Stanislav Tkach Date: Tue Dec 20 20:21:40 2022 +0200 Merge branch 'master' into min-rust-version-in-toml commit bbcd7703b2719125b4261d605e1cbf5325b17956 Author: Stanislav Tkach Date: Tue Dec 20 14:08:21 2022 +0100 Update clap version commit bfecffa327c5d75748bdaec7ff0581109fbb2c90 Author: Stanislav Tkach Date: Sun Dec 18 09:23:16 2022 +0100 Set minimal supported Rust version in the Cargo.toml file commit 3c2f3a33da6fec92a0401477eaae364f1a9cae71 Merge: 4ee6bad 2ed9746 Author: Stanislav Tkach Date: Sat Dec 17 21:44:50 2022 +0200 Merge pull request #324 from stanislav-tkach/dependabot/cargo/clap-4 Update clap requirement from 3 to 4 commit 2ed9746e7769b4b0d834ad3108ba4e04d2f59fc4 Merge: 2263494 4ee6bad Author: Stanislav Tkach Date: Sat Dec 17 21:32:35 2022 +0200 Merge branch 'master' into dependabot/cargo/clap-4 commit 4ee6bad4aa9306eaf271182e507ba688f47baf7b Merge: 7856ea2 5274e8c Author: Stanislav Tkach Date: Sun Nov 27 00:27:50 2022 +0100 Merge pull request #326 from stanislav-tkach/dependabot/cargo/env_logger-0.10 Update env_logger requirement from 0.9 to 0.10 commit 5274e8cec736d8fe3c53acc9e469c2100c4a116f Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri Nov 25 14:02:26 2022 +0000 Update env_logger requirement from 0.9 to 0.10 Updates the requirements on [env_logger](https://github.com/rust-cli/env_logger) to permit the latest version. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.9.0...v0.10.0) --- updated-dependencies: - dependency-name: env_logger dependency-type: direct:production ... Signed-off-by: dependabot[bot] commit 7856ea2c3117c7a691cff66cc97fff14204b9d5a Merge: c79cd09 b566d38 Author: Stanislav Tkach Date: Mon Nov 14 14:19:38 2022 +0100 Merge pull request #325 from kianmeng/fix-typo Fix typo, explictly -> explicitly commit b566d381aa9b8fef3064e94c1308e0c6dcf01019 Author: Kian-Meng Ang Date: Mon Nov 14 10:05:05 2022 +0800 Fix typo, explictly -> explicitly Found via `typos --format brief` commit 22634940a8234688a24448557b9b354929e3bcc3 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu Sep 29 14:10:58 2022 +0000 Update clap requirement from 3 to 4 Updates the requirements on [clap](https://github.com/clap-rs/clap) to permit the latest version. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v3.0.0...v4.0.2) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production ... Signed-off-by: dependabot[bot] commit c79cd093f4facc0783e0c07c948f5f5aa8409299 Merge: 268bb1c 4a13fa0 Author: Stanislav Tkach Date: Mon Sep 19 19:05:07 2022 +0200 Merge pull request #323 from stanislav-tkach/releas-3-5-1 Release the 3.5.1 version commit 4a13fa02bb7790fa388aa27605194dbdf21eb239 Author: Stanislav Tkach Date: Mon Sep 19 18:54:55 2022 +0200 1.45 commit 8e014d4edad1157092644b673b42e18f570e2485 Author: Stanislav Tkach Date: Mon Sep 19 14:51:44 2022 +0200 Update minimal rust version commit 10fc83bf587699a4ef95f5d6f7211f0a5099d73a Author: Stanislav Tkach Date: Sun Sep 18 20:32:16 2022 +0200 Release the 3.5.1 version commit 268bb1cad8c3a20a5039676b95b2c498dbeeb16f Merge: 3dcf623 01713bf Author: Stanislav Tkach Date: Sun Aug 28 23:01:30 2022 +0200 Merge pull request #322 from Guyutongxue/win-11 Add Windows 11 support commit 01713bf250b82649bf858c990d0a603cecb6ea19 Author: Guyutongxue Date: Sun Aug 21 14:20:00 2022 +0800 Add Windows 11 support commit 3dcf623af582e9f6a08c81483269289caa77a9eb Merge: e3320f5 156063b Author: Stanislav Tkach Date: Mon Aug 1 16:48:06 2022 +0200 Merge pull request #321 from stanislav-tkach/releas-3-5-0 Releas the 3.5.0 version commit 156063b672d7da766166e84e96b30ee0880c51ac Author: Stanislav Tkach Date: Mon Aug 1 14:17:43 2022 +0200 Allow the unicode license commit f915220dab6d06899ecab93978801a2481ff5b95 Author: Stanislav Tkach Date: Mon Aug 1 14:16:23 2022 +0200 Remove the doc test commit b73bb8f49dd856f5d8acac373156afd0f29861b0 Author: Stanislav Tkach Date: Sun Jul 31 11:36:29 2022 +0200 Remove ignored doc-tests commit ef3ee1b07d8e92ebe2dbccbe4c4c7e3843ef62ba Author: Stanislav Tkach Date: Sun Jul 31 11:28:05 2022 +0200 Release the 3.5.0 version commit e3320f574b1d7c4cedad26b6a45147a620ae7c5c Merge: 01ed4ee e98db60 Author: Stanislav Tkach Date: Sun Jul 24 01:03:46 2022 +0200 Merge pull request #317 from exincore/improve-os-release-detection Fix linux file_release detection commit e98db60d16c26776b5a86ea360ac3f9219c41e3d Author: exin Date: Mon Jul 18 15:01:49 2022 -0600 Fix file_release inadequate testing * Refactor tests to have more operating system context * Add tests for more edge cases * Order tests alphabetically commit 517e13e043d3a6c6e464e8c334a1d946d8445c8a Author: exin Date: Sat Jul 16 22:26:09 2022 -0600 Refactor DISTRIBUTIONS order commit b780ea4c0dab7f67cb819f574f9714989c98fd76 Author: exin Date: Sat Jul 16 21:55:21 2022 -0600 Fix cspell-dictionary commit b9cf38daed3beb4a686d7b7049161cccd3e5f549 Author: exin Date: Sat Jul 16 21:37:08 2022 -0600 Fix file_release clippy warnings commit 7d86cae863c4b18087bd34dc7045d8a62bff6155 Author: exin Date: Wed Jul 13 20:31:52 2022 -0600 Add ReleaseInfo documentation commit 18e4e69783bbb0e6cd5e6d931691ad2a85dc48e2 Author: exin Date: Sun Jul 10 15:34:05 2022 -0600 Fix linux file_release detection * Fix retrieve function fails to fail * Fix Oracle Linux false positive condition * Refactor ReleaseInfo Matcher to function pointers * Refactor DISTRIBUTIONS to static * Add os-release match closure * Add ReleaseInfo fmt::Debug implementation and tests * Remove get_type function Closes #315 commit b59b672937fddbdaa884537626fbd1293c729755 Author: exin Date: Sat Jul 9 19:49:09 2022 -0500 Remove Matcher::KeyValue match laziness Closes #316 commit 01ed4eeb30cc2c9f6ef251853fc9aec0fc99367a Merge: 8ecb4df ab3a75c Author: Stanislav Tkach Date: Mon Jun 20 13:36:09 2022 +0200 Merge pull request #314 from tukanoidd/master Added Garuda Linux support commit ab3a75cd1f592aeb4da790382079d6f535aaf2db Author: tukanoidd Date: Fri Jun 17 22:59:46 2022 +0200 Added Garuda Linux support commit 8ecb4df3e67fa3d27829f75433fa984abf2154b3 Merge: f255a61 fe86641 Author: Stanislav Tkach Date: Wed May 25 20:59:53 2022 +0200 Merge pull request #311 from cuviper/os-release-rhel Improve RHEL detection in /etc/os-release commit fe86641a4c352ab70816167ee7dff173ce7e1b25 Author: Josh Stone Date: Tue May 24 11:53:38 2022 -0700 Improve RHEL detection in /etc/os-release commit f255a61adb26532fe88ac2c07b8ce226df21c66d Merge: c1385ff e65af14 Author: Stanislav Tkach Date: Sun May 22 19:28:30 2022 +0200 Merge pull request #310 from stanislav-tkach/release-3-4-0 Release the 3.4.0 version commit e65af14ea2e186067807417e406c36a1bd985e07 Author: Stanislav Tkach Date: Sat May 21 23:25:22 2022 +0200 Release the 3.4.0 version commit c1385ff886b77feb0a331738036102ae061f8687 Merge: 6d7a3e0 c0f9604 Author: Stanislav Tkach Date: Fri May 20 10:23:22 2022 +0200 Merge pull request #309 from martintc/master Fix #308: Behavior break on FreeBSD to return Type::Unknown commit c0f960432b5649bbd6e1e771f6d01d0d04c9acbf Author: Todd Martin Date: Wed May 18 18:52:23 2022 -0700 Change generic OK to return Type::FreeBSD commit 6d7a3e0ee7fd71777af0a2b80894c1004bce85cc Merge: a80877c 5f19116 Author: Stanislav Tkach Date: Tue May 17 19:22:38 2022 +0200 Merge pull request #307 from mt-inside/gentoo-linux Add detection of Gentoo Linux commit 5f19116c1d09a9f326a6bdde4e0f62a757c329c3 Author: Matt Turner Date: Tue May 17 09:09:22 2022 +0000 Add detection of Gentoo Linux commit a80877cbe52106e2e85ef245a6b1b4a002f00f68 Merge: 0a812b4 3b44fa6 Author: Stanislav Tkach Date: Sun May 1 22:19:30 2022 +0200 Merge pull request #306 from stanislav-tkach/release-3-3-0 Release the 3.3.0 version commit 3b44fa64a01b0a54851986eb348fc63d024f5e92 Author: Stanislav Tkach Date: Sat Apr 30 21:52:09 2022 +0200 Release the 3.3.0 version commit 0a812b4edca07e49b73d6f83015d9220edcb11c5 Merge: 36c19ad 63f4239 Author: Stanislav Tkach Date: Wed Apr 27 18:11:13 2022 +0200 Merge pull request #305 from martintc/Illumos Initial implementation of Illumos support commit 63f423936b5d62477a73c6f43b4c1b059a3be39b Author: Todd Martin Date: Mon Apr 25 08:57:09 2022 -0700 Correction, return Bitness::X32 when it see "32\n" commit b317711afcd9c9eb733b8f28d2d115b5242f45cf Author: Todd Martin Date: Mon Apr 25 08:53:59 2022 -0700 Add isainfo commit ebc3b0e146a543f7918b83d57c70144aaaeb6e6f Author: Todd Martin Date: Mon Apr 25 08:50:01 2022 -0700 Make use of isainfo for bitness uname and getconf do not report properly, but isainfo does commit 18fb0512f9f0fce7d36982e20211dce11176da16 Author: Todd Martin Date: Mon Apr 25 08:45:26 2022 -0700 Make 'I' lowercase since this is illumos convention commit 725203ac2bced2abc15fc9e7549c09b9bcb40a3b Author: Todd Martin Date: Mon Apr 25 01:49:15 2022 -0700 Add illumos commit 45492bca9d237c4d65bab3dab37bcd7012454186 Author: Todd Martin Date: Mon Apr 25 01:47:46 2022 -0700 Format fixes commit d1090530a7870987d4d6295174b220c166c7209e Author: Todd Martin Date: Mon Apr 25 01:47:33 2022 -0700 Add illumos to the readme commit 9dfb19539eb5f3558d3c21f8c4a4674e96155333 Author: Todd Martin Date: Mon Apr 25 01:44:09 2022 -0700 Implement private function to get version on illumos commit d4b3fae08bf90b35cbf0ff98d21c16663a1af4b6 Author: Todd Martin Date: Mon Apr 25 01:44:00 2022 -0700 Remove function uname for illumos commit 6aed94eaf8c1ae6baa8494bf0231d56382df819a Author: Todd Martin Date: Mon Apr 25 01:41:44 2022 -0700 Add a uname function specifically for illumos commit 70c37c3fa34a17abc1c08589316fd7fc9b99503b Author: Todd Martin Date: Mon Apr 25 01:38:02 2022 -0700 Add illumos targets commit 1c71226274cdce61e33b5f38247c74e18193837d Author: Todd Martin Date: Mon Apr 25 01:35:11 2022 -0700 Try removing new line character commit a219ea8a8744bbb87e36062ac9287839393d14c1 Author: Todd Martin Date: Mon Apr 25 01:33:46 2022 -0700 Add illumos to target list where deps are declared commit 215ad21a95c56134b541500e33947e0e072b0aef Author: Todd Martin Date: Mon Apr 25 01:12:18 2022 -0700 Add a function for bitness detection on illumos commit c38baef38a26ae8de7d5e7d33ca2c6b75be9333e Author: Todd Martin Date: Mon Apr 25 01:12:07 2022 -0700 Create file for illumos commit 4a779ca0342fd2b0dd3cfdb09c65036aa36bb490 Author: Todd Martin Date: Mon Apr 25 00:57:43 2022 -0700 Create a display for illumos commit a9260f8cb5224d2789c4caca040295926ce27931 Author: Todd Martin Date: Mon Apr 25 00:56:24 2022 -0700 Add Illumos to os types list commit 36c19add78efd3cda62397a23bca406bb9bcc7d5 Merge: e4b685e 30874b6 Author: Stanislav Tkach Date: Sun Apr 24 10:10:06 2022 +0200 Merge pull request #303 from martintc/fix-issue-300 Fix issue 300 commit 30874b68bdcd59085d307bd7555e81708b4ea66e Author: Todd Martin Date: Mon Apr 11 03:15:58 2022 -0700 format fixing commit b684911d3679349e42e41cdb9a71294fa6fb01f5 Author: Todd Martin Date: Mon Apr 11 03:09:28 2022 -0700 Removed a trim and created default cases commit 3f4605f0c2920dd384f16c245dec526062235bf5 Author: Todd Martin Date: Mon Apr 11 03:05:35 2022 -0700 Add back in newline escape characters commit d867959aabab677128881ed4c6d21847b037d385 Author: Todd Martin Date: Mon Apr 11 02:59:41 2022 -0700 Use result type instead of unwrapping value --- .github/workflows/version.yml | 2 +- CHANGELOG.md | 54 +- README.md | 15 +- cli/Cargo.toml | 9 +- cspell-dictionary.txt | 22 + deny.toml | 5 +- os_info/Cargo.toml | 13 +- os_info/examples/print_version.rs | 3 +- os_info/src/architecture.rs | 32 ++ os_info/src/bitness.rs | 10 + os_info/src/freebsd/mod.rs | 16 +- os_info/src/illumos/mod.rs | 67 +++ os_info/src/info.rs | 45 +- os_info/src/lib.rs | 16 +- os_info/src/linux/file_release.rs | 540 ++++++++++++------ os_info/src/linux/lsb_release.rs | 39 +- os_info/src/linux/mod.rs | 12 +- .../src/linux/tests/Alpaquita/etc/os-release | 8 + .../tests/{ => Alpine/etc}/alpine-release | 0 .../etc/os-release} | 0 .../etc/os-release} | 0 .../etc/os-release} | 0 os_info/src/linux/tests/Arch/etc/os-release | 11 + .../src/linux/tests/ArchARM/etc/os-release | 11 + os_info/src/linux/tests/Artix/etc/os-release | 9 + .../tests/{ => CentOS/etc}/centos-release | 0 .../etc/os-release} | 0 .../etc/os-release} | 0 .../tests/CentOS_Unknown/etc/centos-release | 1 + .../src/linux/tests/Debian_11/etc/os-release | 9 + .../tests/{ => Fedora/etc}/fedora-release | 0 .../etc/os-release} | 0 .../etc/os-release} | 0 .../tests/Fedora_Unknown/etc/fedora-release | 1 + .../tests/{ => Mariner/etc}/mariner-release | 0 .../tests/Mariner_Unknown/etc/mariner-release | 1 + .../{os-release-mint => Mint/etc/os-release} | 0 .../etc/os-release} | 0 .../linux/tests/OpenCloudOS/etc/os-release | 9 + .../tests/{ => OracleLinux/etc}/os-release | 0 .../tests/OracleLinux/etc/redhat-release | 1 + .../{ => RedHatEnterprise/etc}/redhat-release | 0 .../tests/RedHatEnterprise_7/etc/os-release | 17 + .../etc/os-release} | 0 .../etc/redhat-release | 0 .../etc/os-release} | 0 .../etc/os-release} | 0 .../etc/os-release} | 0 .../none_invalid_os_release/etc/os-release | 2 + .../src/linux/tests/openEuler/etc/os-release | 6 + os_info/src/macos/mod.rs | 3 +- os_info/src/matcher.rs | 6 +- os_info/src/netbsd/mod.rs | 3 +- os_info/src/openbsd/mod.rs | 3 +- os_info/src/os_type.rs | 35 +- os_info/src/version.rs | 8 +- os_info/src/windows/winapi.rs | 169 ++++-- 57 files changed, 944 insertions(+), 269 deletions(-) create mode 100644 os_info/src/architecture.rs create mode 100644 os_info/src/illumos/mod.rs create mode 100644 os_info/src/linux/tests/Alpaquita/etc/os-release rename os_info/src/linux/tests/{ => Alpine/etc}/alpine-release (100%) rename os_info/src/linux/tests/{os-release-alpine-3-12 => Alpine_3_12/etc/os-release} (100%) rename os_info/src/linux/tests/{os-release-amazon-1 => Amazon_1/etc/os-release} (100%) rename os_info/src/linux/tests/{os-release-amazon-2 => Amazon_2/etc/os-release} (100%) create mode 100644 os_info/src/linux/tests/Arch/etc/os-release create mode 100644 os_info/src/linux/tests/ArchARM/etc/os-release create mode 100644 os_info/src/linux/tests/Artix/etc/os-release rename os_info/src/linux/tests/{ => CentOS/etc}/centos-release (100%) rename os_info/src/linux/tests/{os-release-centos => CentOS_7/etc/os-release} (100%) rename os_info/src/linux/tests/{os-release-centos-stream => CentOS_Stream/etc/os-release} (100%) create mode 100644 os_info/src/linux/tests/CentOS_Unknown/etc/centos-release create mode 100644 os_info/src/linux/tests/Debian_11/etc/os-release rename os_info/src/linux/tests/{ => Fedora/etc}/fedora-release (100%) rename os_info/src/linux/tests/{os-release-fedora-32 => Fedora_32/etc/os-release} (100%) rename os_info/src/linux/tests/{os-release-fedora-35 => Fedora_35/etc/os-release} (100%) create mode 100644 os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release rename os_info/src/linux/tests/{ => Mariner/etc}/mariner-release (100%) create mode 100644 os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release rename os_info/src/linux/tests/{os-release-mint => Mint/etc/os-release} (100%) rename os_info/src/linux/tests/{os-release-nixos => NixOS/etc/os-release} (100%) create mode 100644 os_info/src/linux/tests/OpenCloudOS/etc/os-release rename os_info/src/linux/tests/{ => OracleLinux/etc}/os-release (100%) create mode 100644 os_info/src/linux/tests/OracleLinux/etc/redhat-release rename os_info/src/linux/tests/{ => RedHatEnterprise/etc}/redhat-release (100%) create mode 100644 os_info/src/linux/tests/RedHatEnterprise_7/etc/os-release rename os_info/src/linux/tests/{os-release-rhel => RedHatEnterprise_8/etc/os-release} (100%) create mode 100644 os_info/src/linux/tests/RedHatEnterprise_Unknown/etc/redhat-release rename os_info/src/linux/tests/{os-release-suse-12 => SUSE_12/etc/os-release} (100%) rename os_info/src/linux/tests/{os-release-suse-15 => SUSE_15/etc/os-release} (100%) rename os_info/src/linux/tests/{os-release-ubuntu => Ubuntu/etc/os-release} (100%) create mode 100644 os_info/src/linux/tests/none_invalid_os_release/etc/os-release create mode 100644 os_info/src/linux/tests/openEuler/etc/os-release diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 418b0e40..751e3a2e 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -19,7 +19,7 @@ jobs: with: # Feel free to bump this version if you need features of newer Rust. # Sync with badge in README.md - toolchain: 1.41.0 + toolchain: 1.60.0 profile: minimal override: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ab13e99..29762e0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,52 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [3.7.0] (2023-03-20) + +- Information about a processor's architecture has been added. (#336) + +- Mabox Linux support has been added. (#338) + +- Alpaquita Linux support has been added. (#340) + +- Artix Linux support has been added. (#342) + +## [3.6.0] (2023-01-30) + +- OpenCloudOS support has been added. (#328) + +- openEuler support has been added. (#328) + +- Arch Linux ARM and Debian ARM detection has been improved. (#331) + +## [3.5.1] (2022-09-19) + +- Windows 11 detection has been fixed. (#322) + +## [3.5.0] (2022-08-01) + +- Red Hat Enterprise Linux detection has been improved. (#311) + +- Garuda Linux support has been added. (#314) + +- The operating system detection from the release files has been improved. (#317) + +## [3.4.0] (2022-05-22) + +- Gentoo Linux support has been added. (#307) + +- FreeSBD detection has been fixed. (#309) + +## [3.3.0] (2022-05-01) + +- Fedora 35 (without `lsb_release`) detection has been fixed. (#293) + +- HardenedBSD support has been added. (#295) + +- Mariner support has been added. (#299) + +- Illumos support has been added. (#305) + ## [3.2.0] (2022-02-04) - MidnightBSD support has been added. (#290) @@ -245,7 +291,13 @@ All notable changes to this project will be documented in this file. The first release containing only minor infrastructural changes and based on [os_type](https://github.com/schultyy/os_type). -[Unreleased]: https://github.com/stanislav-tkach/os_info/compare/v3.2.0...HEAD +[Unreleased]: https://github.com/stanislav-tkach/os_info/compare/v3.7.0...HEAD +[3.7.0]: https://github.com/stanislav-tkach/os_info/compare/v3.6.0...v3.7.0 +[3.6.0]: https://github.com/stanislav-tkach/os_info/compare/v3.5.1...v3.6.0 +[3.5.1]: https://github.com/stanislav-tkach/os_info/compare/v3.5.0...v3.5.1 +[3.5.0]: https://github.com/stanislav-tkach/os_info/compare/v3.4.0...v3.5.0 +[3.4.0]: https://github.com/stanislav-tkach/os_info/compare/v3.3.0...v3.4.0 +[3.3.0]: https://github.com/stanislav-tkach/os_info/compare/v3.2.0...v3.3.0 [3.2.0]: https://github.com/stanislav-tkach/os_info/compare/v3.1.0...v3.2.0 [3.1.0]: https://github.com/stanislav-tkach/os_info/compare/v3.0.9...v3.1.0 [3.0.9]: https://github.com/stanislav-tkach/os_info/compare/v3.0.8...v3.0.9 diff --git a/README.md b/README.md index 2c1fe3ee..6e34f2df 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ **Project details:** [![LoC](https://tokei.rs/b1/github/stanislav-tkach/os_info)](https://github.com/stanislav-tkach/os_info) -![Rust 1.41+ required](https://img.shields.io/badge/rust-1.41+-blue.svg?label=Required%20Rust) +![Rust 1.60+ required](https://img.shields.io/badge/rust-1.41+-blue.svg?label=Required%20Rust) ## Overview @@ -45,12 +45,13 @@ os_info = { version = "3", default-features = false } let info = os_info::get(); // Print full information: -println!("OS information: {}", info); +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`) @@ -78,10 +79,12 @@ os_info --help 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 @@ -89,19 +92,23 @@ Right now, the following operating system types can be returned: - EndeavourOS - Fedora - FreeBSD +- Garuda Linux +- Gentoo Linux - HardenedBSD +- Illumos - Linux -- Linux Mint - macOS (Mac OS X or OS X) - Manjaro +- Mariner - MidnightBSD +- Mint - NetBSD - NixOS - OpenBSD - openSUSE - Oracle Linux - Pop!_OS -- Raspberry OS +- Raspberry Pi OS - Red Hat Linux - Red Hat Enterprise Linux - Redox diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 3ddbb614..d827bc2d 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -11,17 +11,18 @@ keywords = ["cli", "os", "os_type", "os_version", "os_info"] categories = ["command-line-interface", "os"] license = "MIT" edition = "2018" +rust-version = "1.60" [[bin]] name = "os_info" path = "src/main.rs" [dependencies] -os_info = { version = "3.2.0", default-features = false, path = "../os_info" } +os_info = { version = "3.7.0", default-features = false, path = "../os_info" } log = "0.4.5" -env_logger = "0.9" -clap = { version = "3", features = ["derive"] } +env_logger = "0.10" +clap = { version = "4", features = ["derive"] } [dev-dependencies] assert_cmd = "2" -predicates = "2" +predicates = "3" diff --git a/cspell-dictionary.txt b/cspell-dictionary.txt index 27883338..22cd404a 100644 --- a/cspell-dictionary.txt +++ b/cspell-dictionary.txt @@ -1,23 +1,41 @@ aarch64 +almalinux +alpaquita +antergos +aosc +archarm +artix bitness centos clippy +clearos concat +coreos +devuan earmv emscripten endeavouros freebsd +garuda hardenedbsd hbsd +illumos +isainfo libntdll linuxmint +mabox macos +mageia manjaro midnightbsd msvc +musl netbsd nixos openbsd +opencloudos +openeuler +opensuse println raspberry raspbian @@ -28,5 +46,9 @@ serde structopt toml ulyana +virtuozzo winapi +xbian +xenenterprise xenial +xenserver diff --git a/deny.toml b/deny.toml index 00d3157e..9787a0a5 100644 --- a/deny.toml +++ b/deny.toml @@ -66,14 +66,15 @@ ignore = [ [licenses] # The lint level for crates which do not have a detectable license unlicensed = "deny" -# List of explictly allowed licenses +# List of explicitly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.7 short identifier (+ optional exception)]. allow = [ "MIT", "Apache-2.0", + "Unicode-DFS-2016", ] -# List of explictly disallowed licenses +# List of explicitly disallowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.7 short identifier (+ optional exception)]. deny = [ diff --git a/os_info/Cargo.toml b/os_info/Cargo.toml index 4a7312c0..353a4d72 100644 --- a/os_info/Cargo.toml +++ b/os_info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "os_info" -version = "3.2.0" +version = "3.7.0" authors = ["Jan Schulte ", "Stanislav Tkach "] description = "Detect the operating system type and version." documentation = "https://docs.rs/os_info" @@ -11,6 +11,7 @@ keywords = ["os", "os_type", "os_version", "os_info"] categories = ["os"] license = "MIT" edition = "2018" +rust-version = "1.60" [features] default = ["serde"] @@ -20,7 +21,15 @@ log = "0.4.5" serde = { version = "1", features = ["derive"], optional = true } [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3.8", features = ["minwindef", "ntdef", "ntstatus", "sysinfoapi", "winnt", "winuser", "libloaderapi", "processthreadsapi", "winerror", "winreg"] } +windows-sys = { version = "0.45", features = [ + "Win32_Foundation", + "Win32_System_Diagnostics_Debug", + "Win32_System_LibraryLoader", + "Win32_System_SystemInformation", + "Win32_UI_WindowsAndMessaging", + "Win32_System_Registry", + "Win32_System_SystemServices", +]} [dev-dependencies] pretty_assertions = "1" diff --git a/os_info/examples/print_version.rs b/os_info/examples/print_version.rs index 0047fbcc..dc5bbad5 100644 --- a/os_info/examples/print_version.rs +++ b/os_info/examples/print_version.rs @@ -2,7 +2,7 @@ fn main() { let info = os_info::get(); // Print full information: - println!("OS information: {}", info); + println!("OS information: {info}"); // Print information separately: println!("Type: {}", info.os_type()); @@ -10,4 +10,5 @@ fn main() { println!("Edition: {:?}", info.edition()); println!("Codename: {:?}", info.codename()); println!("Bitness: {}", info.bitness()); + println!("Architecture: {:?}", info.architecture()); } diff --git a/os_info/src/architecture.rs b/os_info/src/architecture.rs new file mode 100644 index 00000000..d6de08b2 --- /dev/null +++ b/os_info/src/architecture.rs @@ -0,0 +1,32 @@ +use std::process::Command; + +use log::error; + +pub fn get() -> Option { + 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/os_info/src/bitness.rs b/os_info/src/bitness.rs index 28b6d0ce..dba7e1c8 100644 --- a/os_info/src/bitness.rs +++ b/os_info/src/bitness.rs @@ -4,6 +4,7 @@ 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", @@ -78,6 +79,15 @@ pub fn get() -> Bitness { } } +#[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( diff --git a/os_info/src/freebsd/mod.rs b/os_info/src/freebsd/mod.rs index a094155c..09c8dbe8 100644 --- a/os_info/src/freebsd/mod.rs +++ b/os_info/src/freebsd/mod.rs @@ -29,19 +29,21 @@ fn get_os() -> Type { .output() .expect("Failed to get OS"); - match str::from_utf8(&os.stdout).unwrap() { - "FreeBSD\n" => { + 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).unwrap() { - "" => return Type::HardenedBSD, - _ => return Type::FreeBSD, + match str::from_utf8(&check_hardening.stderr) { + Ok("0\n") => Type::HardenedBSD, + Ok(_) => Type::FreeBSD, + Err(_) => Type::FreeBSD, } } - "MidnightBSD\n" => Type::MidnightBSD, - _ => Type::Unknown, + Ok("MidnightBSD\n") => Type::MidnightBSD, + Ok(_) => Type::Unknown, + Err(_) => Type::Unknown, } } diff --git a/os_info/src/illumos/mod.rs b/os_info/src/illumos/mod.rs new file mode 100644 index 00000000..1f23771f --- /dev/null +++ b/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 { + 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/os_info/src/info.rs b/os_info/src/info.rs index fd96d010..9b1966a7 100644 --- a/os_info/src/info.rs +++ b/os_info/src/info.rs @@ -15,7 +15,7 @@ use super::{Bitness, Type, Version}; /// use os_info; /// /// let info = os_info::get(); -/// println!("OS information: {}", info); +/// println!("OS information: {info}"); /// ``` #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -26,7 +26,7 @@ pub struct Info { pub(crate) version: Version, /// Operating system edition. pub(crate) edition: Option, - /// Operating system edition. + /// Operating system codename. pub(crate) codename: Option, /// Operating system architecture in terms of how many bits compose the basic values it can deal /// with. See `Bitness` for details. @@ -35,6 +35,8 @@ pub struct Info { // system model info pub(crate) model: Option, + /// Processor architecture. + pub(crate) architecture: Option, } impl Info { @@ -51,6 +53,7 @@ impl Info { /// 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 { @@ -59,8 +62,8 @@ impl Info { edition: None, codename: None, bitness: Bitness::Unknown, - model: None - + model: None, + architecture: None, } } @@ -78,6 +81,7 @@ impl Info { /// 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 { @@ -156,6 +160,18 @@ impl Info { /// get system model info pub fn model(&self) -> Option<&str> { self.model.as_ref().map(String::as_ref) + + /// 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) } } @@ -172,10 +188,10 @@ impl Display for Info { write!(f, " {}", self.version)?; } if let Some(ref edition) = self.edition { - write!(f, " ({})", edition)?; + write!(f, " ({edition})")?; } if let Some(ref codename) = self.codename { - write!(f, " ({})", codename)?; + write!(f, " ({codename})")?; } write!(f, " [{}]", self.bitness) } @@ -194,26 +210,32 @@ mod tests { 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, @@ -269,6 +291,14 @@ mod tests { }, "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, @@ -308,7 +338,8 @@ mod tests { edition: Some("edition".to_owned()), codename: Some("codename".to_owned()), bitness: Bitness::X64, - model: None + model: None, + architecture: Some("architecture".to_owned()), }, "Mac OS 10.2.0 (edition) (codename) [64-bit]", ), diff --git a/os_info/src/lib.rs b/os_info/src/lib.rs index 52196f43..26d86467 100644 --- a/os_info/src/lib.rs +++ b/os_info/src/lib.rs @@ -30,6 +30,10 @@ mod imp; #[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; @@ -59,6 +63,7 @@ mod imp; target_os = "dragonfly", target_os = "emscripten", target_os = "freebsd", + target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "netbsd", @@ -69,6 +74,13 @@ mod imp; #[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))] @@ -77,6 +89,7 @@ mod os_type; #[cfg(any( target_os = "dragonfly", target_os = "freebsd", + target_os = "illumos", target_os = "netbsd", target_os = "openbsd" ))] @@ -95,7 +108,7 @@ pub use crate::{bitness::Bitness, info::Info, os_type::Type, version::Version}; /// let info = os_info::get(); /// /// // Print full information: -/// println!("OS information: {}", info); +/// println!("OS information: {info}"); /// /// // Print information separately: /// println!("Type: {}", info.os_type()); @@ -103,6 +116,7 @@ pub use crate::{bitness::Bitness, info::Info, os_type::Type, version::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/os_info/src/linux/file_release.rs b/os_info/src/linux/file_release.rs index b30a9652..e9cb6c3f 100644 --- a/os_info/src/linux/file_release.rs +++ b/os_info/src/linux/file_release.rs @@ -1,124 +1,196 @@ // spell-checker:ignore sles -use std::{fs::File, io::Read, path::Path}; +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 { - retrieve(&DISTRIBUTIONS) + retrieve(&DISTRIBUTIONS, "/") } -fn retrieve(distributions: &[ReleaseInfo]) -> Option { +fn retrieve(distributions: &[ReleaseInfo], root: &str) -> Option { for release_info in distributions { - if !Path::new(release_info.path).exists() { + 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(&release_info.path) { + let mut file = match File::open(&path) { Ok(val) => val, Err(e) => { - warn!("Unable to open {:?} file: {:?}", release_info.path, 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: {:?}", release_info.path, e); + warn!("Unable to read {:?} file: {:?}", &path, e); continue; } - let os_type = Matcher::KeyValue { key: "NAME" } - .find(&file_content) - .and_then(|name| get_type(&name)) - .unwrap_or(release_info.os_type); + let os_type = (release_info.os_type)(&file_content); - let version = release_info - .version_matcher - .find(&file_content) - .map(Version::from_string) - .unwrap_or_else(|| Version::Unknown); + // 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, - version, + os_type: os_type.unwrap(), + version: version.unwrap_or(Version::Unknown), bitness: Bitness::Unknown, ..Default::default() }); } + // Failed to determine os info None } -fn get_type(name: &str) -> Option { - match name.to_lowercase().as_ref() { - "alpine linux" => Some(Type::Alpine), - "amazon linux" => Some(Type::Amazon), - "amazon linux ami" => Some(Type::Amazon), - "arch linux" => Some(Type::Arch), - "centos linux" => Some(Type::CentOS), - "centos stream" => Some(Type::CentOS), - "fedora" => Some(Type::Fedora), - "fedora linux" => Some(Type::Fedora), - "linux mint" => Some(Type::Mint), - "mariner" => Some(Type::Mariner), - "nixos" => Some(Type::NixOS), - "red hat enterprise linux" => Some(Type::Redhat), - "sles" => Some(Type::SUSE), - "ubuntu" => Some(Type::Ubuntu), - _ => None, - } -} - -#[derive(Debug, Clone)] +/// Struct containing information on how to parse distribution info from a release file. +#[derive(Clone)] struct ReleaseInfo<'a> { - os_type: Type, + /// Relative path to the release file this struct corresponds to from root. path: &'a str, - version_matcher: Matcher, + + /// A closure that determines the os type from the release file contents. + os_type: for<'b> fn(&'b str) -> Option, + + /// A closure that determines the os version from the release file contents. + version: for<'b> fn(&'b str) -> Option, +} + +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)) + .field("version", &(self.version as fn(&'a str) -> Option)) + .finish() + } } /// List of all supported distributions and the information on how to parse their version from the /// release file. -const DISTRIBUTIONS: [ReleaseInfo; 6] = [ - // Due to shenanigans with Oracle Linux including an /etc/redhat-release file that states - // that the OS is Red Hat Enterprise Linux, this /etc/os-release file MUST be checked - // before this code checks /etc/redhat-release. If it does not get run first, - // it will unintentionally report that the operating system is Red Hat Enterprise Linux - // instead of Oracle Linux. +static DISTRIBUTIONS: [ReleaseInfo; 6] = [ + // Keep this first; most modern distributions have this file. ReleaseInfo { - os_type: Type::Mariner, - path: "/etc/mariner-release", - version_matcher: Matcher::PrefixedVersion { - prefix: "CBL-Mariner " + 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 { - os_type: Type::CentOS, - path: "/etc/centos-release", - version_matcher: Matcher::PrefixedVersion { prefix: "release" }, + path: "etc/mariner-release", + os_type: |_| Some(Type::Mariner), + version: |release| { + Matcher::PrefixedVersion { + prefix: "CBL-Mariner", + } + .find(release) + .map(Version::from_string) + }, }, ReleaseInfo { - os_type: Type::Fedora, - path: "/etc/fedora-release", - version_matcher: Matcher::PrefixedVersion { prefix: "release" }, + path: "etc/centos-release", + os_type: |_| Some(Type::CentOS), + version: |release| { + Matcher::PrefixedVersion { prefix: "release" } + .find(release) + .map(Version::from_string) + }, }, ReleaseInfo { - os_type: Type::Alpine, - path: "/etc/alpine-release", - version_matcher: Matcher::AllTrimmed, + path: "etc/fedora-release", + os_type: |_| Some(Type::Fedora), + version: |release| { + Matcher::PrefixedVersion { prefix: "release" } + .find(release) + .map(Version::from_string) + }, }, ReleaseInfo { - os_type: Type::OracleLinux, - path: "/etc/os-release", - version_matcher: Matcher::KeyValue { key: "VERSION_ID" }, + path: "etc/alpine-release", + os_type: |_| Some(Type::Alpine), + version: |release| Matcher::AllTrimmed.find(release).map(Version::from_string), }, ReleaseInfo { - os_type: Type::Redhat, - path: "/etc/redhat-release", - version_matcher: Matcher::PrefixedVersion { prefix: "release" }, + path: "etc/redhat-release", + os_type: |_| Some(Type::RedHatEnterprise), + version: |release| { + Matcher::PrefixedVersion { prefix: "release" } + .find(release) + .map(Version::from_string) + }, }, ]; @@ -128,23 +200,21 @@ mod tests { use pretty_assertions::assert_eq; #[test] - fn oracle_linux() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release"; + fn alpaquita_os_release() { + let root = "src/linux/tests/Alpaquita"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::OracleLinux); - assert_eq!(info.version, Version::Semantic(8, 1, 0)); + 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 os_release_alpine_3_12() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-alpine-3-12"; + fn alpine_3_12_os_release() { + let root = "src/linux/tests/Alpine_3_12"; - let info = retrieve(&distributions).unwrap(); + 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); @@ -152,11 +222,21 @@ mod tests { } #[test] - fn os_release_amazon_1() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-amazon-1"; + 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).unwrap(); + 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); @@ -164,11 +244,10 @@ mod tests { } #[test] - fn os_release_amazon_2() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-amazon-2"; + fn amazon_2_os_release() { + let root = "src/linux/tests/Amazon_2"; - let info = retrieve(&distributions).unwrap(); + 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); @@ -176,11 +255,43 @@ mod tests { } #[test] - fn os_release_centos() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-centos"; + 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).unwrap(); + 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); @@ -188,11 +299,10 @@ mod tests { } #[test] - fn os_release_centos_stream() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-centos-stream"; + fn centos_stream_os_release() { + let root = "src/linux/tests/CentOS_Stream"; - let info = retrieve(&distributions).unwrap(); + 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); @@ -200,11 +310,43 @@ mod tests { } #[test] - fn os_release_fedora() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-fedora-32"; + 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).unwrap(); + 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); @@ -212,11 +354,10 @@ mod tests { } #[test] - fn os_release_fedora_35() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-fedora-35"; + fn fedora_35_os_release() { + let root = "src/linux/tests/Fedora_35"; - let info = retrieve(&distributions).unwrap(); + 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); @@ -224,11 +365,65 @@ mod tests { } #[test] - fn os_release_nixos() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-nixos"; + 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).unwrap(); + 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, @@ -239,122 +434,141 @@ mod tests { } #[test] - fn os_release_rhel() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-rhel"; + fn none_invalid_os_release() { + let root = "src/linux/tests/none_invalid_os_release"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::Redhat); - assert_eq!(info.version, Version::Semantic(8, 2, 0)); + 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 os_release_suse_12() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-suse-12"; + fn openeuler_os_release() { + let root = "src/linux/tests/openEuler"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::SUSE); - assert_eq!(info.version, Version::Semantic(12, 5, 0)); + 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 os_release_suse_15() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-suse-15"; + fn oracle_linux_os_release() { + let root = "src/linux/tests/OracleLinux"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::SUSE); - assert_eq!(info.version, Version::Semantic(15, 2, 0)); + 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 os_release_ubuntu() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-ubuntu"; + fn rhel_8_os_release() { + let root = "src/linux/tests/RedHatEnterprise_8"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::Ubuntu); - assert_eq!(info.version, Version::Semantic(18, 10, 0)); + 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 os_release_mint() { - let mut distributions = [DISTRIBUTIONS[4].clone()]; - distributions[0].path = "src/linux/tests/os-release-mint"; + fn rhel_7_os_release() { + let root = "src/linux/tests/RedHatEnterprise_7"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::Mint); - assert_eq!(info.version, Version::Semantic(20, 0, 0)); + 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 centos() { - let mut distributions = [DISTRIBUTIONS[1].clone()]; - distributions[0].path = "src/linux/tests/centos-release"; + fn redhat_release() { + let root = "src/linux/tests/RedHatEnterprise"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::CentOS); + 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 fedora() { - let mut distributions = [DISTRIBUTIONS[2].clone()]; - distributions[0].path = "src/linux/tests/fedora-release"; + fn redhat_release_unknown() { + let root = "src/linux/tests/RedHatEnterprise_Unknown"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::Fedora); - assert_eq!(info.version, Version::Semantic(26, 0, 0)); + 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 redhat() { - let mut distributions = [DISTRIBUTIONS[5].clone()]; - distributions[0].path = "src/linux/tests/redhat-release"; + fn suse_12_os_release() { + let root = "src/linux/tests/SUSE_12"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::Redhat); - assert_eq!(info.version, Version::Custom("XX".to_owned())); + 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 alpine() { - let mut distributions = [DISTRIBUTIONS[3].clone()]; - distributions[0].path = "src/linux/tests/alpine-release"; + fn suse_15_os_release() { + let root = "src/linux/tests/SUSE_15"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::Alpine); - assert_eq!(info.version, Version::Custom("A.B.C".to_owned())); + 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 mariner() { - let mut distributions = [DISTRIBUTIONS[0].clone()]; - distributions[0].path = "src/linux/tests/mariner-release"; + fn ubuntu_os_release() { + let root = "src/linux/tests/Ubuntu"; - let info = retrieve(&distributions).unwrap(); - assert_eq!(info.os_type(), Type::Mariner); - assert_eq!(info.version, Version::Semantic(2, 0, 20220210)); + 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/os_info/src/linux/lsb_release.rs b/os_info/src/linux/lsb_release.rs index 56daf09d..a494fce6 100644 --- a/os_info/src/linux/lsb_release.rs +++ b/os_info/src/linux/lsb_release.rs @@ -16,16 +16,23 @@ pub fn get() -> Option { }; 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, @@ -106,6 +113,14 @@ mod tests { 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()); @@ -114,6 +129,14 @@ mod tests { 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()); @@ -270,7 +293,6 @@ mod tests { assert_eq!(parse_results.codename, Some("Mariner".to_string())); } - #[test] fn endeavouros() { let parse_results = parse(endeavouros_file()); @@ -295,6 +317,13 @@ mod tests { " } + 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\ @@ -303,6 +332,14 @@ mod tests { 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\ diff --git a/os_info/src/linux/mod.rs b/os_info/src/linux/mod.rs index 211cf973..ac5c8cc0 100644 --- a/os_info/src/linux/mod.rs +++ b/os_info/src/linux/mod.rs @@ -3,7 +3,7 @@ mod lsb_release; use log::trace; -use crate::{bitness, Info, Type}; +use crate::{architecture, bitness, Info, Type}; pub fn current_platform() -> Info { trace!("linux::current_platform is called"); @@ -12,6 +12,7 @@ pub fn current_platform() -> Info { .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 @@ -25,17 +26,24 @@ mod tests { fn os_type() { let version = current_platform(); match version.os_type() { - Type::Alpine + 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 diff --git a/os_info/src/linux/tests/Alpaquita/etc/os-release b/os_info/src/linux/tests/Alpaquita/etc/os-release new file mode 100644 index 00000000..4c47ccda --- /dev/null +++ b/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/os_info/src/linux/tests/alpine-release b/os_info/src/linux/tests/Alpine/etc/alpine-release similarity index 100% rename from os_info/src/linux/tests/alpine-release rename to os_info/src/linux/tests/Alpine/etc/alpine-release diff --git a/os_info/src/linux/tests/os-release-alpine-3-12 b/os_info/src/linux/tests/Alpine_3_12/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-alpine-3-12 rename to os_info/src/linux/tests/Alpine_3_12/etc/os-release diff --git a/os_info/src/linux/tests/os-release-amazon-1 b/os_info/src/linux/tests/Amazon_1/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-amazon-1 rename to os_info/src/linux/tests/Amazon_1/etc/os-release diff --git a/os_info/src/linux/tests/os-release-amazon-2 b/os_info/src/linux/tests/Amazon_2/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-amazon-2 rename to os_info/src/linux/tests/Amazon_2/etc/os-release diff --git a/os_info/src/linux/tests/Arch/etc/os-release b/os_info/src/linux/tests/Arch/etc/os-release new file mode 100644 index 00000000..8662a54d --- /dev/null +++ b/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/os_info/src/linux/tests/ArchARM/etc/os-release b/os_info/src/linux/tests/ArchARM/etc/os-release new file mode 100644 index 00000000..6218b0e2 --- /dev/null +++ b/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/os_info/src/linux/tests/Artix/etc/os-release b/os_info/src/linux/tests/Artix/etc/os-release new file mode 100644 index 00000000..26279cec --- /dev/null +++ b/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/os_info/src/linux/tests/centos-release b/os_info/src/linux/tests/CentOS/etc/centos-release similarity index 100% rename from os_info/src/linux/tests/centos-release rename to os_info/src/linux/tests/CentOS/etc/centos-release diff --git a/os_info/src/linux/tests/os-release-centos b/os_info/src/linux/tests/CentOS_7/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-centos rename to os_info/src/linux/tests/CentOS_7/etc/os-release diff --git a/os_info/src/linux/tests/os-release-centos-stream b/os_info/src/linux/tests/CentOS_Stream/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-centos-stream rename to os_info/src/linux/tests/CentOS_Stream/etc/os-release diff --git a/os_info/src/linux/tests/CentOS_Unknown/etc/centos-release b/os_info/src/linux/tests/CentOS_Unknown/etc/centos-release new file mode 100644 index 00000000..e6b865bc --- /dev/null +++ b/os_info/src/linux/tests/CentOS_Unknown/etc/centos-release @@ -0,0 +1 @@ +Centos Linux diff --git a/os_info/src/linux/tests/Debian_11/etc/os-release b/os_info/src/linux/tests/Debian_11/etc/os-release new file mode 100644 index 00000000..611cf746 --- /dev/null +++ b/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/os_info/src/linux/tests/fedora-release b/os_info/src/linux/tests/Fedora/etc/fedora-release similarity index 100% rename from os_info/src/linux/tests/fedora-release rename to os_info/src/linux/tests/Fedora/etc/fedora-release diff --git a/os_info/src/linux/tests/os-release-fedora-32 b/os_info/src/linux/tests/Fedora_32/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-fedora-32 rename to os_info/src/linux/tests/Fedora_32/etc/os-release diff --git a/os_info/src/linux/tests/os-release-fedora-35 b/os_info/src/linux/tests/Fedora_35/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-fedora-35 rename to os_info/src/linux/tests/Fedora_35/etc/os-release diff --git a/os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release b/os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release new file mode 100644 index 00000000..adc01153 --- /dev/null +++ b/os_info/src/linux/tests/Fedora_Unknown/etc/fedora-release @@ -0,0 +1 @@ +Fedora (Foo Bar) diff --git a/os_info/src/linux/tests/mariner-release b/os_info/src/linux/tests/Mariner/etc/mariner-release similarity index 100% rename from os_info/src/linux/tests/mariner-release rename to os_info/src/linux/tests/Mariner/etc/mariner-release diff --git a/os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release b/os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release new file mode 100644 index 00000000..d64fd530 --- /dev/null +++ b/os_info/src/linux/tests/Mariner_Unknown/etc/mariner-release @@ -0,0 +1 @@ +CBL-Mariner \ No newline at end of file diff --git a/os_info/src/linux/tests/os-release-mint b/os_info/src/linux/tests/Mint/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-mint rename to os_info/src/linux/tests/Mint/etc/os-release diff --git a/os_info/src/linux/tests/os-release-nixos b/os_info/src/linux/tests/NixOS/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-nixos rename to os_info/src/linux/tests/NixOS/etc/os-release diff --git a/os_info/src/linux/tests/OpenCloudOS/etc/os-release b/os_info/src/linux/tests/OpenCloudOS/etc/os-release new file mode 100644 index 00000000..4bc4580f --- /dev/null +++ b/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/os_info/src/linux/tests/os-release b/os_info/src/linux/tests/OracleLinux/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release rename to os_info/src/linux/tests/OracleLinux/etc/os-release diff --git a/os_info/src/linux/tests/OracleLinux/etc/redhat-release b/os_info/src/linux/tests/OracleLinux/etc/redhat-release new file mode 100644 index 00000000..994041ed --- /dev/null +++ b/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/os_info/src/linux/tests/redhat-release b/os_info/src/linux/tests/RedHatEnterprise/etc/redhat-release similarity index 100% rename from os_info/src/linux/tests/redhat-release rename to os_info/src/linux/tests/RedHatEnterprise/etc/redhat-release diff --git a/os_info/src/linux/tests/RedHatEnterprise_7/etc/os-release b/os_info/src/linux/tests/RedHatEnterprise_7/etc/os-release new file mode 100644 index 00000000..ec038b12 --- /dev/null +++ b/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/os_info/src/linux/tests/os-release-rhel b/os_info/src/linux/tests/RedHatEnterprise_8/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-rhel rename to os_info/src/linux/tests/RedHatEnterprise_8/etc/os-release diff --git a/os_info/src/linux/tests/RedHatEnterprise_Unknown/etc/redhat-release b/os_info/src/linux/tests/RedHatEnterprise_Unknown/etc/redhat-release new file mode 100644 index 00000000..e69de29b diff --git a/os_info/src/linux/tests/os-release-suse-12 b/os_info/src/linux/tests/SUSE_12/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-suse-12 rename to os_info/src/linux/tests/SUSE_12/etc/os-release diff --git a/os_info/src/linux/tests/os-release-suse-15 b/os_info/src/linux/tests/SUSE_15/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-suse-15 rename to os_info/src/linux/tests/SUSE_15/etc/os-release diff --git a/os_info/src/linux/tests/os-release-ubuntu b/os_info/src/linux/tests/Ubuntu/etc/os-release similarity index 100% rename from os_info/src/linux/tests/os-release-ubuntu rename to os_info/src/linux/tests/Ubuntu/etc/os-release diff --git a/os_info/src/linux/tests/none_invalid_os_release/etc/os-release b/os_info/src/linux/tests/none_invalid_os_release/etc/os-release new file mode 100644 index 00000000..92258e65 --- /dev/null +++ b/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/os_info/src/linux/tests/openEuler/etc/os-release b/os_info/src/linux/tests/openEuler/etc/os-release new file mode 100644 index 00000000..bd72dd82 --- /dev/null +++ b/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/os_info/src/macos/mod.rs b/os_info/src/macos/mod.rs index 0c93a971..aef79d27 100644 --- a/os_info/src/macos/mod.rs +++ b/os_info/src/macos/mod.rs @@ -2,7 +2,7 @@ use std::process::Command; use log::{trace, warn}; -use crate::{bitness, matcher::Matcher, Info, Type, Version}; +use crate::{architecture, bitness, matcher::Matcher, Info, Type, Version}; pub fn current_platform() -> Info { trace!("macos::current_platform is called"); @@ -11,6 +11,7 @@ pub fn current_platform() -> Info { os_type: Type::Macos, version: version(), bitness: bitness::get(), + architecture: architecture::get(), ..Default::default() }; trace!("Returning {:?}", info); diff --git a/os_info/src/matcher.rs b/os_info/src/matcher.rs index f8acba37..fcc31bc5 100644 --- a/os_info/src/matcher.rs +++ b/os_info/src/matcher.rs @@ -33,10 +33,8 @@ impl Matcher { fn find_by_key<'a>(string: &'a str, key: &str) -> Option<&'a str> { let key = [key, "="].concat(); for line in string.lines() { - if let Some(key_start) = line.find(&key) { - return Some( - line[key_start + key.len()..].trim_matches(|c: char| c == '"' || c.is_whitespace()), - ); + if line.starts_with(&key) { + return Some(line[key.len()..].trim_matches(|c: char| c == '"' || c.is_whitespace())); } } diff --git a/os_info/src/netbsd/mod.rs b/os_info/src/netbsd/mod.rs index d5ab97bf..7031820b 100644 --- a/os_info/src/netbsd/mod.rs +++ b/os_info/src/netbsd/mod.rs @@ -2,7 +2,7 @@ use std::process::Command; use log::{error, trace}; -use crate::{bitness, uname::uname, Info, Type, Version}; +use crate::{architecture, bitness, uname::uname, Info, Type, Version}; pub fn current_platform() -> Info { trace!("netbsd::current_platform is called"); @@ -15,6 +15,7 @@ pub fn current_platform() -> Info { os_type: Type::NetBSD, version, bitness: bitness::get(), + architecture: architecture::get(), ..Default::default() }; diff --git a/os_info/src/openbsd/mod.rs b/os_info/src/openbsd/mod.rs index 897fc4ae..c9eeee4d 100644 --- a/os_info/src/openbsd/mod.rs +++ b/os_info/src/openbsd/mod.rs @@ -2,7 +2,7 @@ use std::process::Command; use log::{error, trace}; -use crate::{bitness, uname::uname, Info, Type, Version}; +use crate::{architecture, bitness, uname::uname, Info, Type, Version}; pub fn current_platform() -> Info { trace!("openbsd::current_platform is called"); @@ -15,6 +15,7 @@ pub fn current_platform() -> Info { os_type: Type::OpenBSD, version, bitness: bitness::get(), + architecture: architecture::get(), ..Default::default() }; diff --git a/os_info/src/os_type.rs b/os_info/src/os_type.rs index 5b59d07d..6d78f587 100644 --- a/os_info/src/os_type.rs +++ b/os_info/src/os_type.rs @@ -6,6 +6,8 @@ use std::fmt::{self, Display, Formatter}; #[allow(non_camel_case_types, clippy::upper_case_acronyms)] #[non_exhaustive] pub enum Type { + /// Alpaquita Linux (). + Alpaquita, /// Alpine Linux (). Alpine, /// Amazon Linux AMI (). @@ -14,6 +16,8 @@ pub enum Type { Android, /// Arch Linux (). Arch, + /// Artix Linux (). + Artix, /// CentOS (). CentOS, /// Debian (). @@ -28,19 +32,27 @@ pub enum Type { Fedora, /// FreeBSD (). FreeBSD, - /// Linux based operating system (). + /// Garuda Linux () + Garuda, + /// Gentoo Linux (). + Gentoo, + /// HardenedBSD (https://hardenedbsd.org/). HardenedBSD, - /// HardenedBSD (https://hardenedbsd.org/) + /// Illumos (https://en.wikipedia.org/wiki/Illumos). + Illumos, + /// Linux based operating system (). Linux, + /// Mabox (). + Mabox, /// Mac OS X/OS X/macOS (). Macos, /// Manjaro (). Manjaro, /// Mariner (). Mariner, - /// Mint (). + /// MidnightBSD (). MidnightBSD, - /// MidnightBSD(). + /// Mint (). Mint, /// NetBSD (). NetBSD, @@ -48,6 +60,10 @@ pub enum Type { NixOS, /// OpenBSD (). OpenBSD, + /// OpenCloudOS (). + OpenCloudOS, + /// openEuler (). + openEuler, /// openSUSE (). openSUSE, /// Oracle Linux (). @@ -83,10 +99,15 @@ impl Default for Type { 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"), @@ -95,7 +116,7 @@ impl Display for Type { 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), + _ => write!(f, "{self:?}"), } } } @@ -112,16 +133,20 @@ mod tests { #[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"), diff --git a/os_info/src/version.rs b/os_info/src/version.rs index 20a2c4a6..578464c6 100644 --- a/os_info/src/version.rs +++ b/os_info/src/version.rs @@ -55,15 +55,15 @@ 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::Semantic(major, minor, patch) => write!(f, "{major}.{minor}.{patch}"), Self::Rolling(ref date) => { let date = match date { - Some(date) => format!(" ({})", date), + Some(date) => format!(" ({date})"), None => "".to_owned(), }; - write!(f, "Rolling Release{}", date) + write!(f, "Rolling Release{date}") } - Self::Custom(ref version) => write!(f, "{}", version), + Self::Custom(ref version) => write!(f, "{version}"), } } } diff --git a/os_info/src/windows/winapi.rs b/os_info/src/windows/winapi.rs index 59e3f30d..0a72239f 100644 --- a/os_info/src/windows/winapi.rs +++ b/os_info/src/windows/winapi.rs @@ -7,45 +7,44 @@ use std::{ ffi::{OsStr, OsString}, - mem, + mem::{self, MaybeUninit}, 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, +use windows_sys::Win32::{ + Foundation::{ERROR_SUCCESS, FARPROC, NTSTATUS, STATUS_SUCCESS}, + System::{ + Diagnostics::Debug::{ + PROCESSOR_ARCHITECTURE_AMD64, PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARCHITECTURE_IA64, + PROCESSOR_ARCHITECTURE_INTEL, }, - winreg::{RegOpenKeyExW, RegQueryValueExW, HKEY_LOCAL_MACHINE, LSTATUS}, - winuser::{GetSystemMetrics, SM_SERVERR2}, + LibraryLoader::{GetModuleHandleA, GetProcAddress}, + Registry::{RegOpenKeyExW, RegQueryValueExW, HKEY_LOCAL_MACHINE, KEY_READ, REG_SZ}, + SystemInformation::{GetNativeSystemInfo, GetSystemInfo, SYSTEM_INFO}, + SystemServices::{VER_NT_WORKSTATION, VER_SUITE_WH_SERVER}, }, + UI::WindowsAndMessaging::{GetSystemMetrics, SM_SERVERR2}, }; use crate::{Bitness, Info, Type, Version}; #[cfg(target_arch = "x86")] -type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXA; +type OSVERSIONINFOEX = windows_sys::Win32::System::SystemInformation::OSVERSIONINFOEXA; #[cfg(not(target_arch = "x86"))] -type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXW; +type OSVERSIONINFOEX = windows_sys::Win32::System::SystemInformation::OSVERSIONINFOEXW; pub fn get() -> Info { let (version, edition) = version(); + let native_system_info = native_system_info(); + Info { os_type: Type::Windows, version, edition, bitness: bitness(), + architecture: architecture(native_system_info), ..Default::default() } } @@ -59,11 +58,38 @@ fn version() -> (Version, Option) { v.dwMinorVersion as u64, v.dwBuildNumber as u64, ), - product_name().or_else(|| edition(&v)), + product_name(&v).or_else(|| edition(&v)), ), } } +// According to https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info +// there is a variant for AMD64 CPUs, but it's not defined in generated bindings. +const PROCESSOR_ARCHITECTURE_ARM64: u16 = 12; + +fn native_system_info() -> SYSTEM_INFO { + let mut system_info: MaybeUninit = MaybeUninit::zeroed(); + unsafe { + GetNativeSystemInfo(system_info.as_mut_ptr()); + }; + + unsafe { system_info.assume_init() } +} + +fn architecture(system_info: SYSTEM_INFO) -> Option { + let cpu_architecture = unsafe { system_info.Anonymous.Anonymous.wProcessorArchitecture }; + + match cpu_architecture { + PROCESSOR_ARCHITECTURE_AMD64 => Some("x86_64"), + PROCESSOR_ARCHITECTURE_IA64 => Some("ia64"), + PROCESSOR_ARCHITECTURE_ARM => Some("arm"), + PROCESSOR_ARCHITECTURE_ARM64 => Some("aarch64"), + PROCESSOR_ARCHITECTURE_INTEL => Some("i386"), + _ => None, + } + .map(str::to_string) +} + #[cfg(target_pointer_width = "64")] fn bitness() -> Bitness { // x64 program can only run on x64 Windows. @@ -72,13 +98,8 @@ fn bitness() -> Bitness { #[cfg(target_pointer_width = "32")] fn bitness() -> Bitness { - use winapi::{ - shared::{ - minwindef::{BOOL, FALSE, PBOOL}, - ntdef::HANDLE, - }, - um::processthreadsapi::GetCurrentProcess, - }; + use windows_sys::Win32::Foundation::{BOOL, FALSE, HANDLE}; + use windows_sys::Win32::System::Threading::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 @@ -88,7 +109,7 @@ fn bitness() -> Bitness { Some(val) => val, }; - type IsWow64 = unsafe extern "system" fn(HANDLE, PBOOL) -> BOOL; + type IsWow64 = unsafe extern "system" fn(HANDLE, *mut BOOL) -> BOOL; let is_wow_64: IsWow64 = unsafe { mem::transmute(is_wow_64) }; let mut result = FALSE; @@ -116,7 +137,7 @@ fn version_info() -> Option { let rtl_get_version: RtlGetVersion = unsafe { mem::transmute(rtl_get_version) }; let mut info: OSVERSIONINFOEX = unsafe { mem::zeroed() }; - info.dwOSVersionInfoSize = mem::size_of::() as DWORD; + info.dwOSVersionInfoSize = mem::size_of::() as u32; if unsafe { rtl_get_version(&mut info) } == STATUS_SUCCESS { Some(info) @@ -125,23 +146,27 @@ fn version_info() -> Option { } } -fn product_name() -> Option { - const REG_SUCCESS: LSTATUS = ERROR_SUCCESS as LSTATUS; - +fn product_name(info: &OSVERSIONINFOEX) -> Option { let sub_key = to_wide("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"); - let mut key = ptr::null_mut(); + let mut key = Default::default(); if unsafe { RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub_key.as_ptr(), 0, KEY_READ, &mut key) } - != REG_SUCCESS - || key.is_null() + != ERROR_SUCCESS + || key == 0 { 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("ProductName"); - let mut data_type: DWORD = 0; - let mut data_size: DWORD = 0; + let name = to_wide(if is_win_11 { + "EditionID" + } else { + "ProductName" + }); + let mut data_type = 0; + let mut data_size = 0; if unsafe { RegQueryValueExW( key, @@ -151,7 +176,7 @@ fn product_name() -> Option { ptr::null_mut(), &mut data_size, ) - } != REG_SUCCESS + } != ERROR_SUCCESS || data_type != REG_SZ || data_size == 0 || data_size % 2 != 0 @@ -168,10 +193,10 @@ fn product_name() -> Option { name.as_ptr(), ptr::null_mut(), ptr::null_mut(), - data.as_mut_ptr() as LPBYTE, + data.as_mut_ptr().cast(), &mut data_size, ) - } != REG_SUCCESS + } != ERROR_SUCCESS || data_size as usize != data.len() * 2 { return None; @@ -186,14 +211,18 @@ fn product_name() -> Option { _ => {} } - Some( - OsString::from_wide(data.as_slice()) - .to_string_lossy() - .into_owned(), - ) + 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 { +fn to_wide(value: &str) -> Vec { OsStr::new(value).encode_wide().chain(Some(0)).collect() } @@ -203,10 +232,16 @@ fn edition(version_info: &OSVERSIONINFOEX) -> Option { match ( version_info.dwMajorVersion, version_info.dwMinorVersion, - version_info.wProductType, + version_info.wProductType as u32, ) { // Windows 10. - (10, 0, VER_NT_WORKSTATION) => Some("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"), @@ -224,12 +259,13 @@ fn edition(version_info: &OSVERSIONINFOEX) -> Option { let mut info: SYSTEM_INFO = unsafe { mem::zeroed() }; unsafe { GetSystemInfo(&mut info) }; - if Into::::into(version_info.wSuiteMask) & VER_SUITE_WH_SERVER + if Into::::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 + } else if version_info.wProductType == VER_NT_WORKSTATION as u8 + && unsafe { info.Anonymous.Anonymous.wProcessorArchitecture } + == PROCESSOR_ARCHITECTURE_AMD64 { Some("Windows XP Professional x64 Edition") } else { @@ -251,8 +287,8 @@ fn get_proc_address(module: &[u8], proc: &[u8]) -> Option { "Procedure name should be zero-terminated" ); - let handle = unsafe { GetModuleHandleA(module.as_ptr() as LPCSTR) }; - if handle.is_null() { + let handle = unsafe { GetModuleHandleA(module.as_ptr()) }; + if handle == 0 { log::error!( "GetModuleHandleA({}) failed", String::from_utf8_lossy(module) @@ -260,7 +296,7 @@ fn get_proc_address(module: &[u8], proc: &[u8]) -> Option { return None; } - unsafe { Some(GetProcAddress(handle, proc.as_ptr() as LPCSTR)) } + unsafe { Some(GetProcAddress(handle, proc.as_ptr())) } } #[cfg(test)] @@ -283,7 +319,6 @@ mod tests { #[test] fn get_edition() { let test_data = [ - (10, 0, VER_NT_WORKSTATION, "Windows 10"), (10, 0, 0, "Windows Server 2016"), (6, 3, VER_NT_WORKSTATION, "Windows 8.1"), (6, 3, 0, "Windows Server 2012 R2"), @@ -306,7 +341,7 @@ mod tests { for &(major, minor, product_type, expected_edition) in &test_data { info.dwMajorVersion = major; info.dwMinorVersion = minor; - info.wProductType = product_type; + info.wProductType = product_type as u8; let edition = edition(&info).unwrap(); assert_eq!(edition, expected_edition); @@ -349,9 +384,29 @@ mod tests { assert!(address.is_some()); } + #[test] + fn get_architecture() { + let cpu_types: [(u16, Option); 6] = [ + (PROCESSOR_ARCHITECTURE_AMD64, Some("x86_64".to_owned())), + (PROCESSOR_ARCHITECTURE_ARM, Some("arm".to_owned())), + (PROCESSOR_ARCHITECTURE_ARM64, Some("aarch64".to_owned())), + (PROCESSOR_ARCHITECTURE_IA64, Some("ia64".to_owned())), + (PROCESSOR_ARCHITECTURE_INTEL, Some("i386".to_owned())), + (0xffff, None), + ]; + + let mut native_info = native_system_info(); + + for cpu_type in cpu_types { + native_info.Anonymous.Anonymous.wProcessorArchitecture = cpu_type.0; + assert_eq!(architecture(native_info), cpu_type.1); + } + } + #[test] fn get_product_name() { - let edition = product_name().expect("edition() failed"); + let version = version_info().expect("version_info() failed"); + let edition = product_name(&version).expect("edition() failed"); assert!(!edition.is_empty()); }