Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion docs/src/extensions.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- spell-checker:ignore hhhhp armv7 cccccccccccccccccccccccccccccccdp ccccccccccccccd ccccccccccccccdp fffffffp -->
<!-- spell-checker:ignore hhhhp armv7 cccccccccccccccccccccccccccccccdp ccccccccccccccd ccccccccccccccdp fffffffp kdump ppc64le mipsel mips64el riscv powerpc sparc sysinfo armv -->

# Extensions over GNU

Expand Down Expand Up @@ -205,3 +205,33 @@ With `-U`/`--no-utf8`, you can interpret input files as 8-bit ASCII rather than
## `install`

`install` offers FreeBSD's `-U` unprivileged option to not change the owner, the group, or the file flags of the destination.

## `uname`

GNU coreutils uses platform-specific mechanisms to determine processor type on modern
systems (e.g., `sysinfo(SI_ARCHITECTURE)` on Solaris, `sysctl()` on BSD, compile-time
architecture detection on macOS). On Linux systems without these mechanisms, it returns
"unknown" for `uname -p`.

uutils takes a different approach: it maps machine architecture strings (from `uname -m`)
to processor types. This provides consistent, useful output on all platforms for packages
that depend on processor type information (e.g., kdump-tools).

**Current mappings:**

| Machine (`uname -m`) | Processor (`uname -p`) |
| -------------------- | ---------------------- |
| arm64, aarch64, arm, armv7l, armv8l, armv7, armv8 | arm |
| x86_64, amd64 | x86_64 |
| i386, i486, i586, i686 | i386 |
| ppc, ppc64, ppc64le, ppc32 | powerpc |
| riscv32, riscv64 | riscv |
| sparc, sparc64 | sparc |
| mips, mipsel, mips64, mips64el | mips |
| (other) | unknown |

**Differences from GNU:**

* uutils uses runtime string matching rather than compile-time detection (e.g., `__arm__`, `__x86_64__` macros on macOS)
* uutils does not use `sysinfo(SI_ARCHITECTURE)` or `sysctl()` fallbacks available on some platforms
* The mapping is based on `uname -m` output rather than platform-specific system calls
42 changes: 38 additions & 4 deletions src/uu/uname/src/uname.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (API) nodename osname sysname (options) mnrsv mnrsvo
// spell-checker:ignore (API) nodename osname sysname (options) mnrsv mnrsvo armv kdump ppc64le mipsel mips64el riscv

use std::ffi::{OsStr, OsString};

Expand All @@ -28,6 +28,40 @@ pub mod options {
pub static OS: &str = "operating-system";
}

/// Map machine architecture string to processor type.
///
/// This provides GNU coreutils-compatible processor type mappings from machine
/// architecture strings. Previously returned "unknown" causing regressions in
/// packages like kdump-tools.
///
/// Mapping table:
/// - arm64, aarch64 → "arm"
/// - x86_64, amd64 → "x86_64"
/// - i386, i486, i586, i686 → "i386"
/// - ppc, ppc64, ppc64le → "powerpc"
/// - riscv32, riscv64 → "riscv"
/// - arm, armv7l, armv8l → "arm"
/// - (other) → "unknown"
fn map_processor(machine: &str) -> String {
match machine {
// ARM architectures
"arm64" | "aarch64" => "arm".to_string(),
"arm" | "armv7l" | "armv8l" | "armv7" | "armv8" => "arm".to_string(),
// x86 architectures
"x86_64" | "amd64" => "x86_64".to_string(),
"i386" | "i486" | "i586" | "i686" => "i386".to_string(),
// PowerPC architectures (matches GNU coreutils on Apple)
"ppc" | "ppc64" | "ppc64le" | "ppc32" => "powerpc".to_string(),
// RISC-V architectures
"riscv32" | "riscv64" => "riscv".to_string(),
// SPARC
"sparc" | "sparc64" => "sparc".to_string(),
// MIPS
"mips" | "mipsel" | "mips64" | "mips64el" => "mips".to_string(),
_ => "unknown".to_string(),
}
}

pub struct UNameOutput {
pub kernel_name: Option<OsString>,
pub nodename: Option<OsString>,
Expand Down Expand Up @@ -84,9 +118,9 @@ impl UNameOutput {

let os = (opts.os || opts.all).then(|| uname.osname().to_owned());

// This option is unsupported on modern Linux systems
// See: https://lists.gnu.org/archive/html/bug-coreutils/2005-09/msg00063.html
let processor = opts.processor.then(|| translate!("uname-unknown").into());
let processor = opts
.processor
.then(|| map_processor(&uname.machine().to_string_lossy()).into());

// This option is unsupported on modern Linux systems
// See: https://lists.gnu.org/archive/html/bug-coreutils/2005-09/msg00063.html
Expand Down
31 changes: 30 additions & 1 deletion tests/by-util/test_uname.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore armv mipsel
use uutests::at_and_ucmd;
use uutests::new_ucmd;

Expand All @@ -28,7 +29,35 @@ fn test_uname_name() {
#[test]
fn test_uname_processor() {
let result = new_ucmd!().arg("-p").succeeds();
assert_eq!(result.stdout_str().trim_end(), "unknown");
let processor = result.stdout_str().trim();

// Verify it's non-empty
assert!(!processor.is_empty());

let machine = new_ucmd!().arg("-m").succeeds().stdout_move_str();
let machine = machine.trim();

// The processor (-p) should be a mapped version of the machine (-m)
// following the logic in src/uu/uname/src/uname.rs
let expected = match machine {
// ARM architectures
"arm64" | "aarch64" => "arm",
"arm" | "armv7l" | "armv8l" | "armv7" | "armv8" => "arm",
// x86 architectures
"x86_64" | "amd64" => "x86_64",
"i386" | "i486" | "i586" | "i686" => "i386",
// PowerPC architectures
"ppc" | "ppc64" | "ppc64le" | "ppc32" => "powerpc",
// RISC-V architectures
"riscv32" | "riscv64" => "riscv",
// SPARC
"sparc" | "sparc64" => "sparc",
// MIPS
"mips" | "mipsel" | "mips64" | "mips64el" => "mips",
_ => "unknown",
};

assert_eq!(processor, expected);
}

#[test]
Expand Down
Loading