diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..6ff73fd --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,17 @@ +# CodeCov configuration +# ref: + +#comment: false ## disable PR coverage commentary posts + +coverage: + status: + # `informational: true` == show status but prevent blocking/failure of CI + project: + default: + informational: true + changes: + default: + informational: true + patch: + default: + informational: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0044574..7a42acd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,89 +1,112 @@ -# spell-checker:ignore (rust) clippy rustfmt rustup RUSTC RUSTFLAGS Zpanic Cpanic RUSTDOCFLAGS Ccodegen Coverflow profraw -# spell-checker:ignore (abbrevs/acronyms) MSVC (bash) alnum esac (jargon) maint (utils) codecov grcov lcov (vars) tempfile () ntempfile +# spell-checker:ignore (rust) clippy rustdoc rustfmt rustup RUSTC RUSTFLAGS Zpanic Cpanic RUSTDOCFLAGS Ccodegen Coverflow profraw +# spell-checker:ignore (abbrevs/acronyms) MSVC (bash) alnum esac (jargon) maint (utils) codecov grcov lcov markdownlint sccache (vars) tempfile () ntempfile uutils +# spell-checker:ignore (people) dtolnay ; Swatinem ; DavidAnson on: [push, pull_request] -name: Basic CI +name: CI + +env: + PROJECT_NAME: platform-info + PROJECT_DESC: 'Cross-platform host machine info' + PROJECT_AUTH: 'uutils' + # * `rust` caching configuration + RUSTC_WRAPPER: 'sccache' + SCCACHE_GHA_ENABLED: 'true' + +# terminate execution of the current workflow group when there is a newer changeset detected +# * the group is defined by "WORKFLOW_NAME-REF", where REF can be a branch, tag, or pull-request reference +# * workflows executing for the default branch are excluded from termination +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }} jobs: - check: - name: cargo check - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macOS-latest, windows-latest] + style_format: + name: Style/format + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Install `rust` toolchain - shell: bash - env: - TOOLCHAIN: stable - run: | - ## Install `rust` toolchain - rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt} - rustup toolchain install ${TOOLCHAIN} -c rustfmt --profile minimal - rustup default ${TOOLCHAIN} - - run: cargo check - - run: cargo check --examples + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - uses: Swatinem/rust-cache@v2 + - uses: mozilla-actions/sccache-action@v0.0.3 + - run: cargo fmt --all -- --check - test: - name: cargo test + style_lint: + name: Style/lint runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [ubuntu-latest, macOS-latest, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v3 - - name: Install `rust` toolchain - shell: bash - env: - TOOLCHAIN: stable - run: | - ## Install `rust` toolchain - rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt} - rustup toolchain install ${TOOLCHAIN} -c rustfmt --profile minimal - rustup default ${TOOLCHAIN} - - run: cargo test - env: - RUST_BACKTRACE: '1' + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + - uses: mozilla-actions/sccache-action@v0.0.3 + - uses: DavidAnson/markdownlint-cli2-action@v10 + with: + command: fix + globs: | + *.md + docs/src/**/*.md + src/**/*.md + - run: cargo clippy --all-targets -- -D warnings - fmt: - name: cargo fmt + style_spellcheck: + name: Style/spellcheck runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Install `rust` toolchain - shell: bash - env: - TOOLCHAIN: stable - run: | - ## Install `rust` toolchain - rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt} - rustup toolchain install ${TOOLCHAIN} -c rustfmt --profile minimal - rustup default ${TOOLCHAIN} - - run: rustup component add rustfmt - - run: cargo fmt --all -- --check + - uses: streetsidesoftware/cspell-action@v2 ## ref: + with: + incremental_files_only: false + verbose: true - clippy: - name: cargo clippy + test: + name: Build/Test runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [ubuntu-latest, macOS-latest, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v3 - - name: Install `rust` toolchain + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - uses: mozilla-actions/sccache-action@v0.0.3 + - name: Build/Test Info shell: bash - env: - TOOLCHAIN: stable run: | - ## Install `rust` toolchain - rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt} - rustup toolchain install ${TOOLCHAIN} -c rustfmt --profile minimal - rustup default ${TOOLCHAIN} - - run: rustup component add clippy - - run: cargo clippy -- -D warnings - - run: cargo clippy --examples -- -D warnings + ## Build/Test Info + # repo/commit info + echo "## repo/commit" + echo GITHUB_REPOSITORY=${GITHUB_REPOSITORY} + echo GITHUB_REF=${GITHUB_REF} + echo GITHUB_SHA=${GITHUB_SHA} + # environment + echo "## environment" + echo "CI='${CI}'" + echo "PWD='${PWD}'" + # tooling info display + echo "## tooling" + which gcc >/dev/null 2>&1 && (gcc --version | head -1) || true + rustup -V 2>/dev/null + rustup show active-toolchain + cargo -V + rustc -V + # dependencies + echo "## crate dependency list" + # * note: for applications, use `--locked` for `cargo fetch`` and `cargo tree`) and commit *Cargo.lock* + cargo fetch --quiet + cargo tree --edges=no-dev --prefix=none --workspace | grep -vE "\(.*[/\\]${GITHUB_REPOSITORY##*/}\)" | sort --unique + - run: cargo test --all-features -- --test-threads 1 + env: + RUST_BACKTRACE: '1' coverage: name: Code Coverage @@ -92,9 +115,9 @@ jobs: fail-fast: true matrix: job: - - { os: ubuntu-latest, features: unix } - - { os: macos-latest, features: macos } - - { os: windows-latest, features: windows } + - { os: ubuntu-latest } + - { os: macos-latest } + - { os: windows-latest } steps: - uses: actions/checkout@v3 - name: Initialize/setup workflow @@ -112,7 +135,9 @@ jobs: outputs TOOLCHAIN # target-specific options # * CARGO_FEATURES_OPTION - CARGO_FEATURES_OPTION='--all -- --check' ; ## default to '--all-features' for code coverage + CARGO_FEATURES_OPTION='--all-features' ; ## default to '--all-features' for code coverage + if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features=${{ matrix.job.features }}' ; fi + outputs CARGO_FEATURES_OPTION # * CODECOV_FLAGS CODECOV_FLAGS=$( echo "${{ matrix.job.os }}" | sed 's/[^[:alnum:]]/_/g' ) outputs CODECOV_FLAGS @@ -123,16 +148,12 @@ jobs: outputs COVERAGE_REPORT_DIR PROFILES_DIR LLVM_PROFILE_FILE="${PROFILES_DIR}/profile-%p-%m.profraw" outputs LLVM_PROFILE_FILE - - name: Install `rust` toolchain - shell: bash - env: - TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }} - run: | - ## Install `rust` toolchain - rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt} - rustup toolchain install ${TOOLCHAIN} -c rustfmt --profile minimal - rustup component add --toolchain ${TOOLCHAIN} llvm-tools - rustup default ${TOOLCHAIN} + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ steps.vars.outputs.TOOLCHAIN }} + components: llvm-tools + - uses: Swatinem/rust-cache@v2 + - uses: mozilla-actions/sccache-action@v0.0.3 - run: cargo install grcov - name: Test shell: bash @@ -144,7 +165,7 @@ jobs: RUSTDOCFLAGS: '' run: | ## Test - cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast + cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast -- --test-threads 1 - name: Test examples shell: bash env: @@ -154,8 +175,8 @@ jobs: RUSTFLAGS: '-C instrument-coverage' RUSTDOCFLAGS: '' run: | - ## Test - cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --examples --no-fail-fast + ## Test examples + cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --examples --no-fail-fast -- --test-threads 1 - name: Generate coverage data (via `grcov`) id: coverage shell: bash diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..c413d1e --- /dev/null +++ b/.mailmap @@ -0,0 +1,10 @@ +## spell-checker:disable +Alex Lyon +Ingvar Stepanyan +Sylvestre Ledru +# +dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +dependabot[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> +dependabot[bot] +# +renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> diff --git a/.vscode/cSpell.json b/.vscode/cSpell.json new file mode 100644 index 0000000..3c62d12 --- /dev/null +++ b/.vscode/cSpell.json @@ -0,0 +1,32 @@ +// `cspell` settings +{ + // version of the setting file + "version": "0.2", + + // spelling language + "language": "en", + + // custom dictionaries + "dictionaries": ["acronyms+names", "jargon", "people", "shell", "workspace"], + "dictionaryDefinitions": [ + { "name": "acronyms+names", "path": "./cspell.dictionaries/acronyms+names.wordlist.txt" }, + { "name": "jargon", "path": "./cspell.dictionaries/jargon.wordlist.txt" }, + { "name": "people", "path": "./cspell.dictionaries/people.wordlist.txt" }, + { "name": "shell", "path": "./cspell.dictionaries/shell.wordlist.txt" }, + { "name": "workspace", "path": "./cspell.dictionaries/workspace.wordlist.txt" } + ], + + // files to ignore (globs supported) + "ignorePaths": [ + "Cargo.lock", + "target/**", + "tests/**/fixtures/**", + "vendor/**" + ], + + // words to ignore (even if they are in the flagWords) + "ignoreWords": [], + + // words to always consider correct + "words": [] +} diff --git a/.vscode/cspell.dictionaries/acronyms+names.wordlist.txt b/.vscode/cspell.dictionaries/acronyms+names.wordlist.txt new file mode 100644 index 0000000..8711913 --- /dev/null +++ b/.vscode/cspell.dictionaries/acronyms+names.wordlist.txt @@ -0,0 +1,69 @@ +# * abbreviations / acronyms +AIX +ASLR # address space layout randomization +AST # abstract syntax tree +CICD # continuous integration/deployment +CPU +CPUs +DevOps +Ext3 +FIFO +FIFOs +FQDN # fully qualified domain name +GID # group ID +GIDs +GNU +GNUEABI +GNUEABIhf +JFS +MSRV # minimum supported rust version +MSVC +NixOS +POSIX +POSIXLY +RISC +RISCV +RNG # random number generator +RNGs +ReiserFS +Solaris +UID # user ID +UIDs +UUID # universally unique identifier +WASI +WASM +XFS +aarch +flac +impls +lzma + +# * names +BusyBox +BusyTest +Codacy +Cygwin +Deno +EditorConfig +FreeBSD +Gmail +GNU +Illumos +Irix +libfuzzer +MS-DOS +MSDOS +MacOS +MinGW +Minix +NetBSD +Novell +OpenBSD +POSIX +PowerPC +SELinux +SkyPack +Solaris +SysV +Xenix +Yargs diff --git a/.vscode/cspell.dictionaries/jargon.wordlist.txt b/.vscode/cspell.dictionaries/jargon.wordlist.txt new file mode 100644 index 0000000..dca883d --- /dev/null +++ b/.vscode/cspell.dictionaries/jargon.wordlist.txt @@ -0,0 +1,155 @@ +AFAICT +alloc +arity +autogenerate +autogenerated +autogenerates +bitmask +bitwise +bytewise +canonicalization +canonicalize +canonicalizing +codepoint +codepoints +codegen +colorizable +colorize +coprime +consts +conv +cyclomatic +dedup +deduplication +demangle +denoland +deque +dequeue +dev +devs +discoverability +duplicative +dsync +endianness +enqueue +errored +executable +executables +exponentiate +eval +falsey +fileio +filesystem +filesystems +flamegraph +fullblock +getfacl +gibi +gibibytes +glob +globbing +hardcode +hardcoded +hardcoding +hardfloat +hardlink +hardlinks +hasher +hashsums +infile +iflag +iflags +kibi +kibibytes +libacl +lcase +lossily +lstat +mebi +mebibytes +mergeable +microbenchmark +microbenchmarks +microbenchmarking +multibyte +multicall +noatime +nocache +nocreat +noctty +noerror +nofollow +nolinks +nonblock +nonportable +nonprinting +notrunc +noxfer +ofile +oflag +oflags +peekable +performant +precompiled +precompute +preload +prepend +prepended +primality +pseudoprime +pseudoprimes +quantiles +readonly +reparse +seedable +semver +semiprime +semiprimes +setfacl +shortcode +shortcodes +siginfo +sigusr +subcommand +subexpression +submodule +sync +symlink +symlinks +syscall +syscalls +tokenize +toolchain +truthy +ucase +unbuffered +udeps +unescape +unintuitive +unprefixed +unportable +unsync +urand +whitespace +wordlist +wordlists + +# * abbreviations +consts +deps +dev +maint +proc +procs + +# * constants +xffff + +# * variables +delim +errno +progname +retval +subdir +val +vals diff --git a/.vscode/cspell.dictionaries/people.wordlist.txt b/.vscode/cspell.dictionaries/people.wordlist.txt new file mode 100644 index 0000000..8fe38d8 --- /dev/null +++ b/.vscode/cspell.dictionaries/people.wordlist.txt @@ -0,0 +1,182 @@ +Akira Hayakawa + Akira + Hayakawa +Alan Andrade + Alan + Andrade +Aleksander Bielawski + Aleksander + Bielawski +Alex Lyon + Alex + Lyon +Alexander Batischev + Alexander + Batischev +Alexander Fomin + Alexander + Fomin +Anthony Deschamps + Anthony + Deschamps +Árni Dagur + Árni + Dagur +Ben Eills + Ben + Eills +Ben Hirsch + Ben + Hirsch +Benoit Benedetti + Benoit + Benedetti +Boden Garman + Boden + Garman +Chirag B Jadwani + Chirag + Jadwani +Derek Chiang + Derek + Chiang +Dorota Kapturkiewicz + Dorota + Kapturkiewicz +Evgeniy Klyuchikov + Evgeniy + Klyuchikov +Fangxu Hu + Fangxu + Hu +Gil Cottle + Gil + Cottle +Haitao Li + Haitao + Li +Inokentiy Babushkin + Inokentiy + Babushkin +Jan Scheer * jhscheer + Jan + Scheer + jhscheer +Jeremiah Peschka + Jeremiah + Peschka +Jian Zeng + Jian + Zeng +Jimmy Lu + Jimmy + Lu +Joao Oliveira + Joao + Oliveira +Jordi Boggiano + Jordi + Boggiano +Jordy Dickinson + Jordy + Dickinson +Joseph Crail + Joseph + Crail +Joshua S Miller + Joshua + Miller +Konstantin Pospelov + Konstantin + Pospelov +Maciej Dziardziel + Maciej + Dziardziel +Martin Kysel + Martin + Kysel +Michael Debertol + Michael + Debertol +Michael Gehring + Michael + Gehring +Mitchell Mebane + Mitchell + Mebane +Morten Olsen Lysgaard + Morten + Olsen + Lysgaard +Nicholas Juszczak + Nicholas + Juszczak +Nick Platt + Nick + Platt +Orvar Segerström + Orvar + Segerström +Peter Atashian + Peter + Atashian +Robert Swinford + Robert + Swinford +Rolf Morel + Rolf + Morel +Roman Gafiyatullin + Roman + Gafiyatullin +Roy Ivy III * rivy + Roy + Ivy + III + rivy +Sergey "Shnatsel" Davidoff + Sergey Shnatsel Davidoff + Sergey + Shnatsel + Davidoff +Sokovikov Evgeniy + Sokovikov + Evgeniy +Sunrin SHIMURA + Sunrin + SHIMURA +Sylvestre Ledru + Sylvestre + Ledru +T Jameson Little + Jameson + Little +Thomas Queiroz + Thomas + Queiroz +Tobias Bohumir Schottdorf + Tobias + Bohumir + Schottdorf +Virgile Andreani + Virgile + Andreani +Vsevolod Velichko + Vsevolod + Velichko +Wiktor Kuropatwa + Wiktor + Kuropatwa +Yury Krivopalov + Yury + Krivopalov + +KokaKiwi +Mahkoh +Smigle00 + Smigle00 + Smigle +anonymousknight +kwantam +nicoo +gmnsii diff --git a/.vscode/cspell.dictionaries/shell.wordlist.txt b/.vscode/cspell.dictionaries/shell.wordlist.txt new file mode 100644 index 0000000..16d7b25 --- /dev/null +++ b/.vscode/cspell.dictionaries/shell.wordlist.txt @@ -0,0 +1,101 @@ +# * Mac +clonefile + +# * POSIX +TMPDIR +adduser +csh +globstar +inotify +localtime +mksh +mountinfo +mountpoint +mtab +nullglob +passwd +pipefail +popd +ptmx +pushd +setarch +sh +sudo +sudoedit +tcsh +tzselect +urandom +wtmp +zsh + +# * Windows +APPDATA +COMSPEC +HKCU +HKLM +HOMEDRIVE +HOMEPATH +LOCALAPPDATA +PATHEXT +PATHEXT +SYSTEMROOT +USERDOMAIN +USERNAME +USERPROFILE +procmon + +# * `git` +gitattributes +gitignore + +# * `make` (`gmake`) +CURDIR +GNUMAKEFLAGS +GNUMakefile +LIBPATTERNS +MAKECMDGOALS +MAKEFILES +MAKEFLAGS +MAKELEVEL +MAKESHELL +SHELLSTATUS +VPATH +abspath +addprefix +addsuffix +endef +findstring +firstword +ifeq +ifneq +lastword +notdir +patsubst + + +# * `npm` +preversion + +# * utilities +cachegrind +chglog +codespell +commitlint +dprint +dtrace +gcov +gmake +grcov +grep +markdownlint +rerast +rollup +sed +selinuxenabled +sestatus +vdir +wslpath +xargs + +# * directories +sbin diff --git a/.vscode/cspell.dictionaries/workspace.wordlist.txt b/.vscode/cspell.dictionaries/workspace.wordlist.txt new file mode 100644 index 0000000..6d6533b --- /dev/null +++ b/.vscode/cspell.dictionaries/workspace.wordlist.txt @@ -0,0 +1,336 @@ +# * cargo +cdylib +rlib + +# * crates +advapi +advapi32-sys +aho-corasick +backtrace +blake2b_simd +bstr +bytecount +byteorder +chacha +chrono +conv +corasick +crossterm +exacl +filetime +formatteriteminfo +fsext +fundu +getopts +getrandom +globset +indicatif +itertools +lscolors +mdbook +memchr +multifilereader +onig +ouroboros +peekreader +quickcheck +rand_chacha +ringbuffer +rlimit +rstest +smallvec +tempdir +tempfile +termion +termios +termsize +termwidth +textwrap +thiserror +ureq +walkdir +winapi +xattr + +# * rust/rustc +RUSTDOCFLAGS +RUSTFLAGS +clippy +rustc +rustfmt +rustup +# +bitor # BitOr trait function +bitxor # BitXor trait function +concat +fract +powi +println +repr +rfind +struct +structs +substr +splitn +trunc +uninit + +# * uutils +basenc +chcon +chgrp +chmod +chown +chroot +cksum +csplit +dircolors +hashsum +hostid +logname +mkdir +mkfifo +mknod +mktemp +nohup +nproc +numfmt +pathchk +printenv +printf +readlink +realpath +relpath +rmdir +runcon +shuf +sprintf +stdbuf +stty +tsort +uname +unexpand +whoami + +# * vars/errno +errno +EACCES +EBADF +EBUSY +EEXIST +EINVAL +ENODATA +ENOENT +ENOSYS +ENOTEMPTY +EOPNOTSUPP +EPERM +EROFS + +# * vars/fcntl +F_GETFL + GETFL +fcntl +vmsplice + +# * vars/libc +COMFOLLOW +FILENO +FTSENT +HOSTSIZE +IDSIZE +IFBLK +IFCHR +IFDIR +IFIFO +IFLNK +IFMT +IFREG +IFSOCK +IRGRP +IROTH +IRUSR +ISGID +ISUID +ISVTX +IWGRP +IWOTH +IWUSR +IXGRP +IXOTH +IXUSR +LINESIZE +NAMESIZE +RTLD_NEXT + RTLD +SIGINT +SIGKILL +SIGTERM +SYS_fdatasync +SYS_syncfs +USERSIZE +accpath +addrinfo +addrlen +blocksize +canonname +chroot +dlsym +execvp +fdatasync +freeaddrinfo +getaddrinfo +getegid +geteuid +getgid +getgrgid +getgrnam +getgrouplist +getgroups +getpwent +getpwnam +getpwuid +getuid +inode +inodes +isatty +lchown +pathlen +setgid +setgroups +settime +setuid +socktype +statfs +statp +statvfs +strcmp +strerror +strlen +syncfs +umask +waitpid +wcslen + +# * vars/nix +iovec +unistd + +# * vars/signals +SIGPIPE + +# * vars/std +CString +pathbuf + +# * vars/stat +bavail +bfree +bsize +ffree +frsize +fsid +fstat +fstype +namelen +# unix::fs::MetadataExt +atime # access time +blksize # blocksize for file system I/O +blocks # number of blocks allocated to file +ctime # creation time +dev # ID of device containing the file +gid # group ID of file owner +ino # inode number +mode # permissions +mtime # modification time +nlink # number of hard links to file +rdev # device ID if file is a character/block special file +size # total size of file in bytes +uid # user ID of file owner +nsec # nanosecond measurement scale +# freebsd::MetadataExt +iosize + +# * vars/time +Timespec +isdst +nanos +nsec +nsecs +strftime +strptime +subsec +usec +usecs +utcoff + +# * vars/utmpx +endutxent +getutxent +getutxid +getutxline +pututxline +setutxent +utmp +utmpx +utmpxname + +# * vars/winapi +DWORD +SYSTEMTIME +LPVOID +LPWSTR +ULONG +ULONGLONG +UNLEN +WCHAR +WSADATA +errhandlingapi +fileapi +handleapi +lmcons +minwinbase +minwindef +processthreadsapi +synchapi +sysinfoapi +winbase +winerror +winnt +winsock + +# * vars/selinux +freecon +getfilecon +lgetfilecon +lsetfilecon +setfilecon + +# * vars/uucore +optflag +optflagmulti +optflagopt +optmulti +optopt + +# * uutils +ccmd +coreopts +coreutils +keepenv +libc +libstdbuf +musl +tmpd +ucmd +ucommand +utmpx +uucore +uucore_procs +uudoc +uumain +uutil +uutils + +# * function names +getcwd diff --git a/Cargo.toml b/Cargo.toml index 4a9aeb3..66ef602 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,8 @@ keywords = ["platform", "info", "system"] categories = ["os"] license = "MIT" +# spell-checker:ignore (crates) libc winapi (features) libloaderapi processthreadsapi sysinfoapi winbase winver + [target.'cfg(not(target_os = "windows"))'.dependencies] libc = "0.2" diff --git a/README.md b/README.md index 9363fe2..216e3d0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A simple cross-platform way to get information about the currently running system. -## Example +## Examples This simple example: @@ -21,7 +21,7 @@ This simple example: use platform_info::*; fn main() { - let info = PlatformInfo::new().unwrap(); + let info = PlatformInfo::new().expect("Unable to determine platform info"); // println!("info={:#?}", info); println!("{}", info.sysname().to_string_lossy()); @@ -46,6 +46,8 @@ GNU/Linux > Using `cargo run --example ex` will build and execute this [example code](examples/ex.rs). +Other examples can be found in the [examples](examples) directory. + ## License `platform-info` is licensed under the [MIT License](LICENSE). diff --git a/examples/arch.rs b/examples/arch.rs index 087951c..2ea1a9f 100644 --- a/examples/arch.rs +++ b/examples/arch.rs @@ -6,7 +6,10 @@ use platform_info::*; fn main() { - let info = PlatformInfo::new().unwrap(); + let info = PlatformInfo::new().unwrap_or_else(|err| { + eprintln!("Unable to determine platform info: {}", err); + std::process::exit(1); + }); println!( "{}", match info.machine().to_os_string().into_string() { diff --git a/examples/ex.rs b/examples/ex.rs index 71434db..04c18f4 100644 --- a/examples/ex.rs +++ b/examples/ex.rs @@ -6,8 +6,8 @@ use platform_info::*; fn main() { - let info = PlatformInfo::new().unwrap(); - // println!("info={:#?}", info); + let info = PlatformInfo::new().expect("Unable to determine platform info"); + // println!("info={:#?}", info); // note: info *may* contain extra platform-specific fields println!("{}", info.sysname().to_string_lossy()); println!("{}", info.nodename().to_string_lossy()); diff --git a/src/lib.rs b/src/lib.rs index 2075161..1c5fb8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,32 +4,56 @@ // // For the full copyright and license information, please view the LICENSE file // that was distributed with this source code. -// +// spell-checker:ignore (abbrev/names) MSVC POSIX (names) rivy (rust) rustdoc RUSTDOCFLAGS + +// Documentation +// See or . +// Use `cargo doc --no-deps --open --target=i686-pc-windows-msvc` to view WinOS documentation for this crate. +// Use `cargo doc --no-deps --open --target=i686-unknown-linux-gnu` to view POSIX documentation for this crate. +// * note: `cargo rustdoc` is equivalent to `cargo doc --no-deps` and is what `docs.rs` uses to generate documentation. +// * ref: @@ + +// Enable documentation warnings for missing documentation (for public items) and broken intra-doc links. +// * note: CI documentation linting has all warnings escalated to errors (using `RUSTDOCFLAGS="--deny warnings" cargo doc`) +#![warn(missing_docs)] +#![warn(rustdoc::broken_intra_doc_links)] +// #![doc = include_str!("../README.md")] // ToDO: [2023-05-28; rivy] DRY by instead including README.md as crate documentation /*! -This crate provides the ability to retrieve various information specific to your current platform -without having to use platform-specific methods to so. Currently, only information pertinent to -a utility like [`uname`](https://github.com/uutils/coreutils/blob/main/src/uu/uname/src/uname.rs) is -provided; however, in the future, more functionality may become available. +[![Crates.io](https://img.shields.io/crates/v/platform-info.svg)](https://crates.io/crates/platform-info) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/uutils/platform-info/tree/main/LICENSE) +[![CodeCov](https://codecov.io/gh/uutils/platform-info/branch/main/graph/badge.svg)](https://codecov.io/gh/uutils/platform-info/tree/main) + +This crate provides the ability to retrieve information specific to your current platform via a cross-platform +uname-type API ([`UNameAPI`]). Additional platform-specific information may be supplied within [`PlatformInfo`]. # Usage -This crate is available on [crate.io](https://crates.io/crates/platform-info), so using it in your -project is as simple as adding `platform-info` to your project's `Cargo.toml`, like so: +This crate is available on [crate.io](https://crates.io/crates/platform-info). So, to use it in your project, just add +the following to your project's `Cargo.toml` [dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html): ```toml [dependencies] platform-info = "2" ``` -To see specific usage details, look at the `uname` utility linked above as it makes -use of every feature. +# Examples + +```rust +*/ +#![doc = include_str!("../examples/ex.rs")] +/*! +``` + +Other examples can be found in the [`examples` directory](https://github.com/uutils/platform-info/tree/main/examples) +of this crate and in the [uutils/coreutils](https://github.com/uutils/coreutils) implementation of +[`uname`](https://github.com/uutils/coreutils/blob/main/src/uu/uname/src/uname.rs). */ // spell-checker:ignore (API) nodename osname sysname // spell-checker:ignore (uutils) coreutils uutils -#![warn(unused_results)] +#![warn(unused_results)] // enable warnings for unused results use std::ffi::OsStr; @@ -38,18 +62,22 @@ mod lib_impl; //=== // PlatformInfo -/// Handles initial retrieval and holds cached information for the current platform. -pub type PlatformInfo = lib_impl::PlatformInfo; +// Handles initial retrieval and holds cached information for the current platform. +pub use lib_impl::PlatformInfo; +#[cfg(unix)] +pub use lib_impl::UTSName; +#[cfg(windows)] +pub use lib_impl::{WinApiSystemInfo, WinOsVersionInfo}; // PlatformInfoError -/// The common error type for `PlatformInfo`. -pub type PlatformInfoError = lib_impl::BoxedThreadSafeStdError; +/// The common error type for [`PlatformInfoAPI`]. +pub use lib_impl::BoxedThreadSafeStdError as PlatformInfoError; // PlatformInfoAPI -/// Defines the full API for `PlatformInfo`. +/// Defines the full API for [`PlatformInfo`]. // * includes `UNameAPI` pub trait PlatformInfoAPI: UNameAPI { - /// Creates a new instance of `PlatformInfo`. + /// Creates a new instance of [`PlatformInfo`]. ///
On some platforms, it is possible for this function to fail. fn new() -> Result where diff --git a/src/lib_impl.rs b/src/lib_impl.rs index 17bdcfd..1541f06 100644 --- a/src/lib_impl.rs +++ b/src/lib_impl.rs @@ -1,6 +1,6 @@ // "plumbing" setup and connections for `lib.rs` -#![warn(unused_results)] +#![warn(unused_results)] // enable warnings for unused results #[cfg(target_os = "windows")] use std::path::Path; @@ -9,7 +9,9 @@ use std::path::PathBuf; //=== types +/// Standard thread-safe error type pub type ThreadSafeStdError = dyn std::error::Error + Send + Sync; +/// Standard thread-safe error type (boxed to allow translation for any std::error::Error type) pub type BoxedThreadSafeStdError = Box; /// A slice of a path string diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 7248a1f..1718878 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -17,7 +17,7 @@ // refs: // [Byte-to/from-String Conversions](https://nicholasbishop.github.io/rust-conversions) @@ -#![warn(unused_results)] +#![warn(unused_results)] // enable warnings for unused results use std::ffi::{OsStr, OsString}; use std::fmt; @@ -31,6 +31,7 @@ use unix_safe::*; /// Handles initial retrieval and holds cached information for the current platform (a Unix-like OS in this case). #[derive(Clone, Debug, PartialEq, Eq)] pub struct PlatformInfo { + /// Contains the cached results of the `utsname()` system call. // ref: pub utsname: UTSName, /* aka "Unix Time-sharing System Name"; ref: */ // * private-use fields diff --git a/src/platform/unknown.rs b/src/platform/unknown.rs index 32b02fd..aa01ffe 100644 --- a/src/platform/unknown.rs +++ b/src/platform/unknown.rs @@ -9,7 +9,7 @@ // spell-checker:ignore (names) Ingvar Stepanyan * me@rreverser.com // spell-checker:ignore (uutils) coreutils uutils -#![warn(unused_results)] +#![warn(unused_results)] // enable warnings for unused results use std::ffi::{OsStr, OsString}; diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 656ba49..e38effa 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -28,7 +28,7 @@ // spell-checker:ignore (WinAPI) ctypes CWSTR DWORDLONG dwStrucVersion FARPROC FIXEDFILEINFO HIWORD HMODULE libloaderapi LOWORD LPCSTR LPCVOID LPCWSTR lpdw LPDWORD lplp LPOSVERSIONINFOEXW LPSYSTEM lptstr LPVOID LPWSTR minwindef ntdef ntstatus OSVERSIONINFOEXW processthreadsapi PUINT SMALLBUSINESS SUITENAME sysinfo sysinfoapi sysinfoapi TCHAR TCHARs ULONGLONG VERSIONINFO WCHAR WCHARs winapi winbase winver WSTR wstring // spell-checker:ignore (WinOS) ntdll -#![warn(unused_results)] +#![warn(unused_results)] // enable warnings for unused results use std::convert::TryFrom; use std::ffi::{OsStr, OsString}; @@ -57,8 +57,11 @@ use windows_safe::*; /// Handles initial retrieval and holds cached information for the current platform (Windows/WinOS in this case). #[derive(Clone, Debug, PartialEq, Eq)] pub struct PlatformInfo { + /// Cached computer name. pub computer_name: OsString, + /// Wraps a cached [`WinApiSystemInfo`]. pub system_info: WinApiSystemInfo, + /// Wraps a cached [`WinOsVersionInfo`]. pub version_info: WinOsVersionInfo, // * private-use fields sysname: OsString, @@ -130,7 +133,7 @@ impl UNameAPI for PlatformInfo { /// Contains information about the current computer system. /// /// Wraps [SYSTEM_INFO](https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info). -#[derive(Clone, Copy /* , Debug, PartialEq, Eq */)] +#[derive(Clone, Copy /* , Debug, PartialEq, Eq *//* note: implemented elsewhere */)] pub struct WinApiSystemInfo( // ref: @@ SYSTEM_INFO, @@ -496,11 +499,11 @@ fn determine_machine(system_info: &WinApiSystemInfo) -> OsString { }, PROCESSOR_ARCHITECTURE_IA64 => "ia64", PROCESSOR_ARCHITECTURE_ARM => "arm", // `arm` may be under-specified compared to GNU implementations - PROCESSOR_ARCHITECTURE_ARM64 => "aarch64", + PROCESSOR_ARCHITECTURE_ARM64 => "aarch64", // alternatively, `arm64` may be more correct PROCESSOR_ARCHITECTURE_MIPS => "mips", PROCESSOR_ARCHITECTURE_PPC => "powerpc", PROCESSOR_ARCHITECTURE_ALPHA | PROCESSOR_ARCHITECTURE_ALPHA64 => "alpha", - PROCESSOR_ARCHITECTURE_SHX => "superh", // "SuperH" processor + PROCESSOR_ARCHITECTURE_SHX => "superh", // a "SuperH" processor _ => "unknown", }; diff --git a/src/platform/windows_safe.rs b/src/platform/windows_safe.rs index d2e3dc2..50629ec 100644 --- a/src/platform/windows_safe.rs +++ b/src/platform/windows_safe.rs @@ -8,7 +8,7 @@ // spell-checker:ignore (WinAPI) ctypes CWSTR DWORDLONG dwStrucVersion FARPROC FIXEDFILEINFO HIWORD HMODULE libloaderapi LOWORD LPCSTR LPCVOID LPCWSTR lpdw LPDWORD lplp LPOSVERSIONINFOEXW LPSYSTEM lptstr LPVOID LPWSTR minwindef ntdef ntstatus OSVERSIONINFOEXW processthreadsapi PUINT SMALLBUSINESS SUITENAME sysinfo sysinfoapi sysinfoapi TCHAR TCHARs ULONGLONG WCHAR WCHARs winapi winbase winver WSTR wstring // spell-checker:ignore (WinOS) ntdll -#![warn(unused_results)] +#![warn(unused_results)] // enable warnings for unused results use std::convert::TryFrom; use std::io; @@ -65,6 +65,8 @@ pub struct VS_FIXEDFILEINFO { impl WinApiSystemInfo { #[allow(non_snake_case)] + /// Returns `wProcessorArchitecture` extracted from the [`SYSTEM_INFO`](https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info) structure. + ///
Refer to [`SYSTEM_INFO`](https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info) for more information. pub fn wProcessorArchitecture(&self) -> WORD { unsafe { self.0.u.s().wProcessorArchitecture } } @@ -89,7 +91,7 @@ pub fn create_OSVERSIONINFOEXW( /// When the reference count reaches zero, the module is unloaded from the address space of the calling process and the /// handle is no longer valid. /// -/// *Returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-zero for fn *success*. +/// *Returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-`FALSE` (aka non-zero) for fn *success*. /// /// Wraps WinOS [`Kernel32/FreeLibrary(...)`](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary). #[allow(non_snake_case)] @@ -97,7 +99,7 @@ pub fn WinAPI_FreeLibrary(module: HMODULE /* from `hModule: HMODULE` */) -> BOOL // FreeLibrary // pub unsafe fn FreeLibrary(hLibModule: HMODULE) -> BOOL // ref: @@ - // * *returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-zero for fn *success* + // * *returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-`FALSE` (aka non-zero) for fn *success* unsafe { FreeLibrary(module) } } @@ -112,7 +114,7 @@ pub fn WinAPI_FreeLibrary(module: HMODULE /* from `hModule: HMODULE` */) -> BOOL /// - for non-`FALSE` return, contains the number of TCHARs (aka WCHARs) copied to the destination buffer, *not including* the terminating null character /// - for `FALSE` return, contains the buffer size required for the result, *including* the terminating null character /// -/// *Returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-zero for fn *success*. +/// *Returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-`FALSE` (aka non-zero) for fn *success*. /// ///### Notes /// @@ -139,7 +141,7 @@ where // * `nSize` ~ (in) specifies the size of the destination buffer (*lpBuffer) in TCHARs (aka WCHARs) // * `nSize` ~ (out) on *fn failure* (aka `FALSE` return), receives the buffer size required for the result, *including* the terminating null character // * `nSize` ~ (out) on *fn success*, receives the number of TCHARs (aka WCHARs) copied to the destination buffer, *not including* the terminating null character - // * *returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-zero for fn *success* + // * *returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-`FALSE` (aka non-zero) for fn *success* let maybe_buffer = buffer.into(); let (buffer_ptr, length) = match maybe_buffer { Some(buf) => (buf.as_mut_ptr(), DWORD::try_from(buf.len()).unwrap_or(0)), @@ -189,7 +191,7 @@ pub fn WinAPI_GetFileVersionInfoSizeW>( // WinAPI_GetFileVersionInfoW /// Retrieves version information for the specified file (`file_path`); stored into BYTE vector (`data`). /// -/// *Returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-zero for fn *success*. +/// *Returns* BOOL ~ `FALSE` (aka zero) for fn *failure*; o/w non-`FALSE` (aka non-zero) for fn *success*. /// /// Wraps WinOS [`Version/GetFileVersionInfoW(...)`](https://learn.microsoft.com/en-us/windows/win32/api/winver/nf-winver-getfileversioninfow). #[allow(non_snake_case)] @@ -204,7 +206,7 @@ pub fn WinAPI_GetFileVersionInfoW>( // ref: @@ // * handle/dwHandle == *ignored* // * length/dwLen == maximum size (in bytes) of buffer at data_ptr/lpData - // * *returns* BOOL ~ `FALSE` (aka zero) for fn *failure*, o/w non-zero for fn *success* + // * *returns* BOOL ~ `FALSE` (aka zero) for fn *failure*, o/w non-`FALSE` (aka non-zero) for fn *success* let file_path_cws: CWSTR = to_c_wstring(file_path.as_ref()); unsafe { GetFileVersionInfoW( @@ -327,7 +329,7 @@ pub fn WinAPI_LoadLibrary>( /// Compares a set of operating system version requirements (`version_info`, `type_mask`, and `condition_mask`) to the /// corresponding values for the currently running version of the system. /// -/// *Returns* BOOL ~ `FALSE` (aka zero) if resource is non-existent or requirements are not met; o/w non-`FALSE` +/// *Returns* BOOL ~ `FALSE` (aka zero) if resource is non-existent or requirements are not met; o/w non-`FALSE` (aka non-zero) /// /// Wraps WinOS [`Kernel32/VerifyVersionInfoW(...)`](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-verifyversioninfow). #[allow(non_snake_case)] @@ -342,7 +344,7 @@ pub fn WinAPI_VerifyVersionInfoW( // version_info/lpVersionInformation ~ pointer to (const) version info requirements for comparison // type_mask ~ mask indicating members of version_info to be tested // condition_mask ~ type of comparison for each version_info member to be compared - // * returns BOOL ~ FALSE (aka zero), for non-existent resource or invalid requirements; o/w non-zero + // * returns BOOL ~ `FALSE` (aka zero) for non-existent resource or invalid requirements; o/w non-`FALSE` (aka non-zero) let version_info_ptr: *const OSVERSIONINFOEXW = version_info; unsafe { VerifyVersionInfoW( @@ -373,7 +375,7 @@ pub fn WinAPI_VerQueryValueW<'a, S: AsRef>( // version_info_ptr/pBlock ~ pointer to (const) version info // info_view/lplpBuffer ~ pointer into version info supplied by version_info_ptr (no new allocations) // info_view_length/puLen ~ pointer to size (in characters [TCHARs/WCHARs] for "version info values", in bytes for translation array or root block) - // * returns BOOL ~ `0` (aka `FALSE`), for invalid/non-existent resource; o/w non-zero + // * returns BOOL ~ `FALSE` (aka zero) for invalid/non-existent resource; o/w non-`FALSE` (aka non-zero) let version_info_ptr = version_info.as_ptr() as LPCVOID; unsafe { VerQueryValueW( @@ -430,7 +432,7 @@ pub fn WinOsFileVersionInfoQuery_root( // version_info_ptr/pBlock ~ pointer to (const) version info // info_view/lplpBuffer ~ pointer into version info supplied by version_info_ptr (no new allocations) // info_view_length/puLen ~ pointer to size (in characters [TCHARs/WCHARs] for "version info values", in bytes for translation array or root block) - // * returns BOOL ~ `FALSE` (aka zero), for invalid/non-existent resource; o/w non-zero for *fn success* + // * returns BOOL ~ `FALSE` (aka zero) for invalid/non-existent resource; o/w non-`FALSE` (aka non-zero) for *fn success* let version_info_data = &version_info.data; @@ -558,6 +560,7 @@ fn structure_clone() { dwFileDateLS: 0, }; println!("{:?}", ffi); - let ffi_copy = ffi.clone(); - assert_eq!(ffi_copy, ffi); + #[allow(clippy::clone_on_copy)] // ignore `clippy::clone_on_copy` warning for direct testing + let ffi_clone = ffi.clone(); + assert_eq!(ffi_clone, ffi); } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index bf6d9aa..69bb9f8 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -1,7 +1,5 @@ // spell-checker:ignore (API) nodename osname sysname -use regex; - use platform_info::*; #[test]