Files
s390-tools/rust
Marc Hartmayer 6689e25865 rust: Fix all cargo clippy findings
- Remove useless type conversion in uvdevice.rs
- Replace useless comparison in hostname.rs
- Replace unnecessary unwrap patterns in pvapconfig
- Use sort_by_key instead of sort_by in pvimg example

Command line used to get the findings:

  $ clippy --all-features -- --cap-lints=warn
  warning: useless conversion to the same type: `u64`
    --> pv_core/src/uvdevice.rs:56:28
     |
  56 |         rc = ioctl(raw_fd, cmd.try_into().unwrap(), cb.as_ptr_mut());
     |                            ^^^^^^^^^^^^^^
     |
     = help: consider removing `.try_into()`
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
     = note: `#[warn(clippy::useless_conversion)]` on by default

  warning: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
    --> utils/src/hostname.rs:60:13
     |
  60 |     assert!(isize::try_from(buf_len).unwrap() <= isize::MAX);
     |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: because `isize::MAX` is the maximum value for this type, this comparison is always true
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
     = note: `#[warn(clippy::absurd_extreme_comparisons)]` on by default

  warning: `utils` (lib) generated 1 warning
      Checking pvebc v0.12.0 (/home/mhartmay/git/s390-tools/rust/pvebc)
  warning: consider using `sort_unstable_by_key`
     --> pvapconfig/src/ap.rs:177:9
      |
  177 |         self.0.sort_unstable_by(|a, b| b.gen.cmp(&a.gen));
      |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |
      = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
      = note: `#[warn(clippy::unnecessary_sort_by)]` on by default
  help: try
      |
  177 -         self.0.sort_unstable_by(|a, b| b.gen.cmp(&a.gen));
  177 +         self.0.sort_unstable_by_key(|b| std::cmp::Reverse(b.gen));

  warning: called `unwrap_err` on `r` after checking its variant with `is_err`
    --> pvapconfig/src/main.rs:55:29
     |
  54 |         if $r.is_err() {
     |         -------------- help: try: `if let Err(<item>) = r`
  55 |             eprintln!("{}", $r.unwrap_err());
     |                             ^^^^^^^^^^^^^^^
  ...
  87 |     on_error_print_and_exit!(r);
     |     --------------------------- in this macro invocation
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
     = note: this warning originates in the macro `on_error_print_and_exit` (in Nightly builds, run with -Z macro-backtrace for more info)

  warning: this `repeat().take()` can be written more concisely
    --> pvimg/src/se_img_comps/bootloader/ipl.rs:95:21
     |
  95 |           let comps = iter::repeat(ipl_pb0_pv_comp::default())
     |  _____________________^
  96 | |             .take(num_comp)
     | |___________________________^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(ipl_pb0_pv_comp::default(), num_comp)`
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_repeat_n
     = note: `#[warn(clippy::manual_repeat_n)]` on by default

  warning: this `repeat().take()` can be written more concisely
     --> pvimg/src/se_img_comps/bootloader/ipl.rs:113:21
      |
  113 |         let comps = iter::repeat(comp).take(num_comp).collect();
      |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(comp, num_comp)`
      |
      = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_repeat_n

Reviewed-by: Timo Keller <tkeller@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Marc Hartmayer <marc@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-06-25 14:14:43 +02:00
..
2026-06-22 16:43:02 +02:00
2026-06-25 14:14:43 +02:00
2026-06-25 14:14:43 +02:00
2026-06-25 14:14:43 +02:00
2023-12-01 10:24:48 +01:00
2026-06-22 16:43:02 +02:00
2026-06-22 16:43:02 +02:00

s390-tools tools written in rust

Setting up rust development and build environment

Please refer to the official documentation to set up a working rust environment: https://www.rust-lang.org/learn/get-started

The minimum supported Rust version (MSRV) is 1.75.

Building rust code

s390-tools build system

If cargo is installed a simple make should do the job. Note that, compiling rust programs take significantly longer than C code. To closely monitor the progress use make V=1 By default release builds are made.

With make CARGOFLAGS=<flags> one can pass additional flags to cargo. With make HAVE_CARGO=0 one can turn of any compilation that requires cargo. With make CARGO=<...> one can set the cargo binary

cargo

If you need to run cargo directly, cd to each project you want to build and issue your cargo commands. Do NOT forget to specify --release if you are building tools for a release. The s390-tools expect the environment variable S390_TOOLS_RELEASE to be present at build time. This is the version string the rust tools provide.

Tip: You can use make version to get the version string.

Internal Libraries

  • utils Library for rust tools that bundles common stuff for the 390-tools

    • provides a macro to get the S390_TOOLS_RELEASE string
    • provides macros for compile time assertions
  • pv_core Library for pv tools, providing uvdevice access and utilities to send, receive and interpret various UV-calls.

  • pv Library for pv tools, providing uvdevice access, encryption utilities, and utilities for generating UV-request

    • requires openssl and libcurl
    • reexports ann symbols from pv_core
    • if no encryption utilities required, use pv_core

Writing new tools

We encourage to use Rust for new tools. However, for some use cases it makes sense to use C and C is still allowed to be used for a new tool/library. Exiting tools may be rewritten in Rust.

What (third-party) crates can be used for s390-tools?

A huge list of libraries are made available through Rusts' ecosystem and is one of many upsides. However, just like with Coding Style Guidelines, it is important to limit the usage of those libraries so that within a project, everyone is on the same page and that code written in Rust uses similar approaches. It makes it easier for code review and maintainability in general.

The following list of crates should cover a wide variety of use cases. This list is a start, but can change over time.

  • anyhow
    • Flexible concrete Error type built on std::error::Error
  • base64
    • Encodes and decodes base64 as bytes or utf8
  • byteorder
    • Library for reading/writing numbers in big-endian and little-endian.
  • cfg-if
    • A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted.
  • clap
    • A simple to use, efficient, and full-featured Command Line Argument Parser
  • curl
    • Rust bindings to libcurl for making HTTP requests
  • deku
    • Bit level serialization/deserialization proc-macro for structs
  • libc
    • Raw FFI bindings to platform libraries like libc.
  • log
    • A lightweight logging facade for Rust
  • openssl
    • OpenSSL bindings
  • serde
    • A generic serialization/deserialization framework
  • serde_jsonl
    • A JSON serialization file format
  • serde_yaml
    • YAML data format for Serde
  • thiserror
    • derive(Error)
  • zerocopy
    • Utilities for zero-copy parsing and serialization

Dependencies used by the crates listed above can be used, too.

Add new tool

To add a new tool issue cargo new $TOOLNAME in the rust directory.

Add the tool to the s390-tools build system:

CARGO_TARGETS := $TOOLNAME

Add the library to the s390-tools test list:

CARGO_TEST_TARGETS := $LIBNAME

Add the tool/library to the cargo workspace:

[workspace]
members = [
	"pv",
	"pvsecret",
	"$TOOLNAME",
	"$LIBNAME"
	"utils",
]

Versions

Do not communicate the version defined in the toml file by default. Use release_string from the rust/utils crate instead:

use utils::release_string;

fn print_version() {
    println!(
        "{} version {}\nCopyright IBM Corp. 2023",
        env!("CARGO_PKG_NAME"), // collapses into the crates name
        release_string!() // this (very likely) collapses into a compile time constant
    );
}

Unsafe rust

rust allows you to write unsafe rust. Try to avoid it, it can make rust unsafe. If you need to, e.g. interacting with other languages like C, keep the unsafe block as small as possible and add a reasoning using // SAFETY: why this code is safe. Example:

// Get the raw pointer and do an ioctl.
//
// SAFETY: the passed pointer points to a valid memory region that
// contains the expected C-struct. The struct outlives this function.
unsafe {
    let ptr: *mut ffi::uvio_ioctl_cb = cb as *mut _;
    rc = ioctl(raw_fd, cmd, ptr);
}

Coding style

Make cargo fmt and cargo clippy happy!

Testing

Prefer writing tests using rustdoc. Use explicit rust tests for more edge case tests.