diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 89022bbef..209456092 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -612,11 +612,23 @@ jobs: run: | ## Install/setup prerequisites case '${{ matrix.job.target }}' in - arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;; - aarch64-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;; - *-redox*) sudo apt-get -y update ; sudo apt-get -y install fuse3 libfuse-dev ;; + arm-unknown-linux-gnueabihf) + sudo apt-get -y update + sudo apt-get -y install gcc-arm-linux-gnueabihf + ;; + aarch64-unknown-linux-*) + sudo apt-get -y update + sudo apt-get -y install gcc-aarch64-linux-gnu + ;; + *-redox*) + sudo apt-get -y update + sudo apt-get -y install fuse3 libfuse-dev + ;; # Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368 - x86_64-pc-windows-gnu) C:/msys64/usr/bin/pacman.exe -Syu --needed mingw-w64-x86_64-gcc --noconfirm ; echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH ;; + x86_64-pc-windows-gnu) + C:/msys64/usr/bin/pacman.exe -Syu --needed mingw-w64-x86_64-gcc --noconfirm + echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH + ;; esac case '${{ matrix.job.os }}' in macos-latest) brew install coreutils ;; # needed for testing diff --git a/Cargo.lock b/Cargo.lock index b6a259134..56e448fa7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2616,6 +2616,7 @@ dependencies = [ "unicode-width", "uucore", "uutils_term_grid", + "xattr", ] [[package]] diff --git a/src/uu/ls/Cargo.toml b/src/uu/ls/Cargo.toml index d11eeb27c..38312eefc 100644 --- a/src/uu/ls/Cargo.toml +++ b/src/uu/ls/Cargo.toml @@ -34,6 +34,9 @@ once_cell = { workspace = true } selinux = { workspace = true, optional = true } hostname = { workspace = true } +[target.'cfg(unix)'.dependencies] +xattr = { workspace = true } + [[bin]] name = "ls" path = "src/main.rs" diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 0e9b25722..1c89cd353 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -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 (ToDO) somegroup nlink tabsize dired subdired dtype colorterm +// spell-checker:ignore (ToDO) somegroup nlink tabsize dired subdired dtype colorterm getxattr use clap::{ builder::{NonEmptyStringValueParser, ValueParser}, @@ -36,6 +36,7 @@ use std::{ }; use term_grid::{Cell, Direction, Filling, Grid, GridOptions}; use unicode_width::UnicodeWidthStr; + #[cfg(any( target_os = "linux", target_os = "macos", @@ -2620,6 +2621,18 @@ fn display_grid( Ok(()) } +#[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))] +fn file_has_acl>(file: P) -> bool { + // don't use exacl here, it is doing more getxattr call then needed + match xattr::list(file) { + Ok(acl) => { + // if we have extra attributes, we have an acl + acl.count() > 0 + } + Err(_) => false, + } +} + /// This writes to the BufWriter out a single string of the output of `ls -l`. /// /// It writes the following keys, in order: @@ -2663,9 +2676,14 @@ fn display_item_long( output_display += " "; } if let Some(md) = item.get_metadata(out) { + #[cfg(any(not(unix), target_os = "android", target_os = "macos"))] + // TODO: See how Mac should work here + let is_acl_set = false; + #[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))] + let is_acl_set = file_has_acl(item.display_name.as_os_str()); write!( output_display, - "{}{} {}", + "{}{}{} {}", display_permissions(md, true), if item.security_context.len() > 1 { // GNU `ls` uses a "." character to indicate a file with a security context, @@ -2674,6 +2692,12 @@ fn display_item_long( } else { "" }, + if is_acl_set { + // if acl has been set, we display a "+" at the end of the file permissions + "+" + } else { + "" + }, pad_left(&display_symlink_count(md), padding.link_count) ) .unwrap(); diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 0162b0170..1262c2ab9 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -4293,3 +4293,39 @@ fn test_term_colorterm() { "exe" ); } + +#[cfg(all(unix, not(target_os = "macos")))] +#[test] +fn test_acl_display() { + use std::process::Command; + + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let path = "a42"; + at.mkdir(path); + + let path = at.plus_as_string(path); + // calling the command directly. xattr requires some dev packages to be installed + // and it adds a complex dependency just for a test + match Command::new("setfacl") + .args(["-d", "-m", "group::rwx", &path]) + .status() + .map(|status| status.code()) + { + Ok(Some(0)) => {} + Ok(_) => { + println!("test skipped: setfacl failed"); + return; + } + Err(e) => { + println!("test skipped: setfacl failed with {}", e); + return; + } + } + + scene + .ucmd() + .args(&["-lda", &path]) + .succeeds() + .stdout_contains("+"); +}