diff --git a/src/find/matchers/ls.rs b/src/find/matchers/ls.rs index 9b05f82d..301a6381 100644 --- a/src/find/matchers/ls.rs +++ b/src/find/matchers/ls.rs @@ -11,77 +11,6 @@ use std::{ use super::{Matcher, MatcherIO, WalkEntry}; -#[cfg(unix)] -fn format_permissions(mode: uucore::libc::mode_t) -> String { - let file_type = match mode & (uucore::libc::S_IFMT as uucore::libc::mode_t) { - uucore::libc::S_IFDIR => "d", - uucore::libc::S_IFREG => "-", - _ => "?", - }; - - // S_$$USR means "user permissions" - let user_perms = format!( - "{}{}{}", - if mode & uucore::libc::S_IRUSR != 0 { - "r" - } else { - "-" - }, - if mode & uucore::libc::S_IWUSR != 0 { - "w" - } else { - "-" - }, - if mode & uucore::libc::S_IXUSR != 0 { - "x" - } else { - "-" - } - ); - - // S_$$GRP means "group permissions" - let group_perms = format!( - "{}{}{}", - if mode & uucore::libc::S_IRGRP != 0 { - "r" - } else { - "-" - }, - if mode & uucore::libc::S_IWGRP != 0 { - "w" - } else { - "-" - }, - if mode & uucore::libc::S_IXGRP != 0 { - "x" - } else { - "-" - } - ); - - // S_$$OTH means "other permissions" - let other_perms = format!( - "{}{}{}", - if mode & uucore::libc::S_IROTH != 0 { - "r" - } else { - "-" - }, - if mode & uucore::libc::S_IWOTH != 0 { - "w" - } else { - "-" - }, - if mode & uucore::libc::S_IXOTH != 0 { - "x" - } else { - "-" - } - ); - - format!("{}{}{}{}", file_type, user_perms, group_perms, other_perms) -} - #[cfg(windows)] fn format_permissions(file_attributes: u32) -> String { let mut attributes = Vec::new(); @@ -126,7 +55,7 @@ impl Ls { mut out: impl Write, print_error_message: bool, ) { - use std::os::unix::fs::{MetadataExt, PermissionsExt}; + use std::os::unix::fs::MetadataExt; let metadata = file_info.metadata().unwrap(); @@ -146,8 +75,7 @@ impl Ls { number_of_blocks + (4 - (remainder)) } }; - let permission = - { format_permissions(metadata.permissions().mode() as uucore::libc::mode_t) }; + let permission = uucore::fs::display_permissions(metadata, true); let hard_links = metadata.nlink(); // Fall back to the numeric id when the uid/gid has no passwd/group entry // (unmapped owner) — matching GNU find, which never crashes. uucore::entries @@ -286,24 +214,3 @@ impl Matcher for Ls { true } } - -#[cfg(test)] -mod tests { - #[test] - #[cfg(unix)] - fn test_format_permissions() { - use super::format_permissions; - - let mode: uucore::libc::mode_t = 0o100_644; - let expected = "-rw-r--r--"; - assert_eq!(format_permissions(mode), expected); - - let mode: uucore::libc::mode_t = 0o040_755; - let expected = "drwxr-xr-x"; - assert_eq!(format_permissions(mode), expected); - - let mode: uucore::libc::mode_t = 0o100_777; - let expected = "-rwxrwxrwx"; - assert_eq!(format_permissions(mode), expected); - } -} diff --git a/tests/test_find.rs b/tests/test_find.rs index 35bcb563..f6872585 100644 --- a/tests/test_find.rs +++ b/tests/test_find.rs @@ -1385,6 +1385,24 @@ fn find_ls() { .no_stderr(); } +#[test] +#[cfg(unix)] +fn find_ls_shows_file_type_and_special_bits() { + use std::os::unix::fs::PermissionsExt; + + let temp_dir = Builder::new().prefix("find_ls_modes").tempdir().unwrap(); + let file = temp_dir.path().join("setuid"); + File::create(&file).unwrap(); + fs::set_permissions(&file, fs::Permissions::from_mode(0o4755)).unwrap(); + symlink("setuid", temp_dir.path().join("link")).unwrap(); + + ucmd() + .args(&[temp_dir.path().to_str().unwrap(), "-ls"]) + .succeeds() + .stdout_contains(" -rwsr-xr-x ") + .stdout_contains(" lrwx"); +} + // Regression test for uutils/findutils#717: `-ls` used to abort (exit 101) when // a file's owning uid/gid had no passwd/group entry; it must fall back to the // numeric id like GNU find. Creating such a file needs privilege to chown to an