chcon: link to libfts on musl targets

This fixes a build failure on aarch64-unknown-linux-musl.

On musl‐based targets the fts API is not provided by libc but by a separate libfts library.

* src/uu/chcon/build.rs

Add a build script (`build.rs`) that detects when `CARGO_CFG_TARGET_OS=linux` &&
`CARGO_CFG_TARGET_ENV=musl` and emits `rustc-link-lib=fts`, so that `uu-chcon` can link successfully.

* src/uu/chcon/src/fts.rs

In the glibc version of the header, `level` is `short`, under musl it's `int`; likewise,
`pathlen` is `unsigned` on musl but signed on glibc.
This commit is contained in:
Fredrick Brennan 2025-04-30 15:39:39 -04:00
parent 279629f67e
commit 5c60dbebbc
No known key found for this signature in database
GPG key ID: 5853056962F14E58
2 changed files with 24 additions and 3 deletions

15
src/uu/chcon/build.rs Normal file
View file

@ -0,0 +1,15 @@
use std::env;
pub fn main() {
// Do not rebuild build script unless the script itself or the enabled features are modified
// See <https://doc.rust-lang.org/cargo/reference/build-scripts.html#change-detection>
println!("cargo:rerun-if-changed=build.rs");
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
// On musl, fts is not part of libc, but in its own library.
if target_os == "linux" && target_env == "musl" {
println!("cargo:rustc-link-lib=fts");
}
}

View file

@ -6,7 +6,12 @@
use std::ffi::{CStr, CString, OsStr};
use std::marker::PhantomData;
use std::os::raw::{c_int, c_long, c_short};
use std::os::raw::{c_int, c_long};
// On musl, fts_level is an int, but on glibc it is a short.
#[cfg(target_env = "musl")]
use std::os::raw::c_int as fts_level_t;
#[cfg(target_env = "gnu")]
use std::os::raw::c_short as fts_level_t;
use std::path::Path;
use std::{io, iter, ptr, slice};
@ -142,7 +147,7 @@ impl<'fts> EntryRef<'fts> {
self.as_ref().fts_errno
}
pub(crate) fn level(&self) -> c_short {
pub(crate) fn level(&self) -> fts_level_t {
self.as_ref().fts_level
}
@ -162,7 +167,8 @@ impl<'fts> EntryRef<'fts> {
ptr::NonNull::new(entry.fts_path)
.map(|path_ptr| {
let path_size = usize::from(entry.fts_pathlen).saturating_add(1);
let mut path_size: usize = entry.fts_pathlen as usize;
path_size = path_size.saturating_add(1);
// SAFETY: `entry.fts_path` is a non-null pointer that is assumed to be valid.
unsafe { slice::from_raw_parts(path_ptr.as_ptr().cast(), path_size) }