From baa33be2deefbab86075092b0b9f5470b2dd288d Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Wed, 30 Apr 2025 15:39:39 -0400 Subject: [PATCH] chcon: link to libfts on musl targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/uu/chcon/build.rs | 15 +++++++++++++++ src/uu/chcon/src/fts.rs | 12 +++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/uu/chcon/build.rs diff --git a/src/uu/chcon/build.rs b/src/uu/chcon/build.rs new file mode 100644 index 00000000000..fe8e74ac0a2 --- /dev/null +++ b/src/uu/chcon/build.rs @@ -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 + 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"); + } +} diff --git a/src/uu/chcon/src/fts.rs b/src/uu/chcon/src/fts.rs index b60ac7d3ace..c3e53305c9c 100644 --- a/src/uu/chcon/src/fts.rs +++ b/src/uu/chcon/src/fts.rs @@ -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) }