From bcf6c147943032a43bdb8beefa063870670868c3 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 14:27:09 -0600 Subject: [PATCH 01/11] ls: On Windows don't display files hidden by NTFS This little check, allows us to hide the files that shoulnd't be shown on the listing on Windows operating systems. Just like the "dot" in UNIX based operating systems Windows uses its own file attributes to determine if a file is hidden or not. The lack of support for this option is normally an annoyance for many users, this commit adds full support for this feature --- src/uu/ls/src/ls.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 20100568adb..725ce380187 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -255,6 +255,18 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } } +#[cfg(windows)] +fn is_hidden(file_path: &std::path::PathBuf) -> std::io::Result { + let metadata = fs::metadata(file_path)?; + let attr = metadata.file_attributes(); + + if (attr & 0x2) > 0 { + Ok(true) + } else { + Ok(false) + } +} + #[cfg(windows)] fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { let mut reverse = options.opt_present("r"); @@ -286,6 +298,12 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { let ffi_name = entry.file_name(); let name = ffi_name.to_string_lossy(); + #[cfg(windows)] + let hidden_by_ntfs = is_hidden(&entry.path()).unwrap(); + if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') || hidden_by_ntfs { + return false; + } + #[cfg(unix)] if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') { return false; } From 0fe2dc95982fccebc6910f3605e5a6d89ec16ff4 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 14:45:24 -0600 Subject: [PATCH 02/11] ls: fix build errors --- src/uu/ls/src/ls.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 725ce380187..3dde00caef1 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -295,22 +295,31 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } } +#[cfg(windows)] fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { let ffi_name = entry.file_name(); let name = ffi_name.to_string_lossy(); - #[cfg(windows)] let hidden_by_ntfs = is_hidden(&entry.path()).unwrap(); if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') || hidden_by_ntfs { return false; } - #[cfg(unix)] + if options.opt_present("B") && name.ends_with('~') { + return false; + } + return true +} + +#[cfg(unix)] +fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { + let ffi_name = entry.file_name(); + let name = ffi_name.to_string_lossy(); if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') { return false; } if options.opt_present("B") && name.ends_with('~') { return false; } - true + return true } fn enter_directory(dir: &PathBuf, options: &getopts::Matches) { From f969d72bbe763e6d90f707c6d7413de5737e0c55 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 15:06:45 -0600 Subject: [PATCH 03/11] ls: Refactor the ishidden function and follow rustfmt --- src/uu/ls/src/ls.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 3dde00caef1..e55a361c861 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -260,11 +260,7 @@ fn is_hidden(file_path: &std::path::PathBuf) -> std::io::Result { let metadata = fs::metadata(file_path)?; let attr = metadata.file_attributes(); - if (attr & 0x2) > 0 { - Ok(true) - } else { - Ok(false) - } + Ok((attr & 0x2) > 0) } #[cfg(windows)] From 0210171b4ae0a3f594d75cbaabf707ab623e2f03 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 15:16:43 -0600 Subject: [PATCH 04/11] Run cargo fmt --- src/uu/ls/src/ls.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index e55a361c861..0429d51731b 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -296,13 +296,15 @@ fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { let ffi_name = entry.file_name(); let name = ffi_name.to_string_lossy(); let hidden_by_ntfs = is_hidden(&entry.path()).unwrap(); - if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') || hidden_by_ntfs { + if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') + || hidden_by_ntfs + { return false; } if options.opt_present("B") && name.ends_with('~') { return false; } - return true + return true; } #[cfg(unix)] @@ -315,7 +317,7 @@ fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { if options.opt_present("B") && name.ends_with('~') { return false; } - return true + return true; } fn enter_directory(dir: &PathBuf, options: &getopts::Matches) { From 315bffe39b6c92b03688b8b04e32e71ad77dbe61 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 15:45:37 -0600 Subject: [PATCH 05/11] Tests_ls: Test if hidden files get properly displayed on Windows This also fixes a logic error in the if statement for Windows operating systems --- src/uu/ls/src/ls.rs | 4 ++-- tests/by-util/test_ls.rs | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 0429d51731b..0e2b0ff61f9 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -296,8 +296,8 @@ fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { let ffi_name = entry.file_name(); let name = ffi_name.to_string_lossy(); let hidden_by_ntfs = is_hidden(&entry.path()).unwrap(); - if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') - || hidden_by_ntfs + if !options.opt_present("a") && !options.opt_present("A") && (name.starts_with('.') + || hidden_by_ntfs) { return false; } diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 270849d957f..fe9e213bc8e 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -160,7 +160,7 @@ fn test_ls_order_size() { println!("stdout = {:?}", result.stdout); assert!(result.success); #[cfg(not(windows))] - assert_eq!(result.stdout, "test-1\ntest-2\ntest-3\ntest-4\n"); + assert_eq!(result.stdout, "test-1\ntest-2\ntest-3\ntest-4\tp"); #[cfg(windows)] assert_eq!(result.stdout, "test-1 test-2 test-3 test-4\n"); } @@ -310,3 +310,23 @@ fn test_ls_human() { assert!(result.success); assert!(result.stdout.contains("1.02M")); } + +#[cfg(windows)] +#[test] +fn test_ls_hidden_windows() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let file = "hiddenWindowsFileNoDot"; + at.touch(file); + // hide the file + scene.cmd("attrib").arg("+h").arg("+S").arg("+r").arg(file).run(); + let result = scene.ucmd().run(); + println!("stderr = {:?}", result.stderr); + println!("stdout = {:?}", result.stdout); + assert!(result.success); + let result = scene.ucmd().arg("-a").run(); + println!("stderr = {:?}", result.stderr); + println!("stdout = {:?}", result.stdout); + assert!(result.success); + assert!(result.stdout.contains(file)); +} From 5e171c56899737fe69cc058b4f1c212398efa0df Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 15:47:57 -0600 Subject: [PATCH 06/11] Tests_ls: fix a typo --- tests/by-util/test_ls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index fe9e213bc8e..4ed0b947b8a 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -160,7 +160,7 @@ fn test_ls_order_size() { println!("stdout = {:?}", result.stdout); assert!(result.success); #[cfg(not(windows))] - assert_eq!(result.stdout, "test-1\ntest-2\ntest-3\ntest-4\tp"); + assert_eq!(result.stdout, "test-1\ntest-2\ntest-3\ntest-4\n"); #[cfg(windows)] assert_eq!(result.stdout, "test-1 test-2 test-3 test-4\n"); } From a37a90062c04a4b21c9fcade2b9c99ea395873df Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 16:29:43 -0600 Subject: [PATCH 07/11] ls: Redo is hidden testing to avoid code duplication --- src/uu/ls/src/ls.rs | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 0e2b0ff61f9..2d0fac9b4b0 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -255,12 +255,16 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } } -#[cfg(windows)] -fn is_hidden(file_path: &std::path::PathBuf) -> std::io::Result { - let metadata = fs::metadata(file_path)?; +fn is_hidden(file_path: &DirEntry) -> std::io::Result { + let metadata = fs::metadata(file_path.path())?; let attr = metadata.file_attributes(); - Ok((attr & 0x2) > 0) + + #[cfg(unix)] + return Ok(file_path.file_name().to_string_lossy().starts_with('.')); + + #[cfg(windows)] + return Ok(((attr & 0x2) > 0) || file_path.file_name().to_string_lossy().starts_with('.')); } #[cfg(windows)] @@ -291,33 +295,17 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } } -#[cfg(windows)] -fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { - let ffi_name = entry.file_name(); - let name = ffi_name.to_string_lossy(); - let hidden_by_ntfs = is_hidden(&entry.path()).unwrap(); - if !options.opt_present("a") && !options.opt_present("A") && (name.starts_with('.') - || hidden_by_ntfs) - { - return false; - } - if options.opt_present("B") && name.ends_with('~') { - return false; - } - return true; -} -#[cfg(unix)] fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { let ffi_name = entry.file_name(); let name = ffi_name.to_string_lossy(); - if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') { + if !options.opt_present("a") && !options.opt_present("A") && is_hidden(entry).unwrap() { return false; } if options.opt_present("B") && name.ends_with('~') { return false; } - return true; + true } fn enter_directory(dir: &PathBuf, options: &getopts::Matches) { From 631c98a914411106a8ac5fc21a4fbb04809dfb86 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 16:34:20 -0600 Subject: [PATCH 08/11] Fix build issues on UNIX --- src/uu/ls/src/ls.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 2d0fac9b4b0..13c93d30e75 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -256,14 +256,12 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } fn is_hidden(file_path: &DirEntry) -> std::io::Result { - let metadata = fs::metadata(file_path.path())?; - let attr = metadata.file_attributes(); - - #[cfg(unix)] return Ok(file_path.file_name().to_string_lossy().starts_with('.')); #[cfg(windows)] + let metadata = fs::metadata(file_path.path())?; + let attr = metadata.file_attributes(); return Ok(((attr & 0x2) > 0) || file_path.file_name().to_string_lossy().starts_with('.')); } From 67942eb1b03bef1ab562834ea92687f86f3f63c5 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 16:57:52 -0600 Subject: [PATCH 09/11] ls: Final fixes of UNIX compilation --- src/uu/ls/src/ls.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 13c93d30e75..a4cc91ccbc9 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -255,14 +255,20 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } } +#[cfg(windows)] +fn ntfs_hidden(path: &DirEntry) -> std::io::Result { + let metadata = fs::metadata(path.path())?; + let attr = metadata.file_attributes(); + return Ok((attr & 0x2) > 0); +} + fn is_hidden(file_path: &DirEntry) -> std::io::Result { - #[cfg(unix)] - return Ok(file_path.file_name().to_string_lossy().starts_with('.')); + if file_path.file_name().to_string_lossy().starts_with('.') { + return Ok(true); + } #[cfg(windows)] - let metadata = fs::metadata(file_path.path())?; - let attr = metadata.file_attributes(); - return Ok(((attr & 0x2) > 0) || file_path.file_name().to_string_lossy().starts_with('.')); + return ntfs_hidden(file_path); } #[cfg(windows)] @@ -293,7 +299,6 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } } - fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { let ffi_name = entry.file_name(); let name = ffi_name.to_string_lossy(); From 6dc2078f1263ad584b067d8e65c809cd46b5895a Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Fri, 18 Dec 2020 17:32:42 -0600 Subject: [PATCH 10/11] ls: Refactor is hidden function to fix UNIX issues --- src/uu/ls/src/ls.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index a4cc91ccbc9..e48d0c0dc5a 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -256,19 +256,15 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { } #[cfg(windows)] -fn ntfs_hidden(path: &DirEntry) -> std::io::Result { - let metadata = fs::metadata(path.path())?; +fn is_hidden(file_path: &DirEntry) -> std::io::Result { + let metadata = fs::metadata(file_path.path())?; let attr = metadata.file_attributes(); - return Ok((attr & 0x2) > 0); + return Ok(((attr & 0x2) > 0) || file_path.file_name().to_string_lossy().starts_with('.')); } +#[cfg(unix)] fn is_hidden(file_path: &DirEntry) -> std::io::Result { - if file_path.file_name().to_string_lossy().starts_with('.') { - return Ok(true); - } - - #[cfg(windows)] - return ntfs_hidden(file_path); + return Ok(file_path.file_name().to_string_lossy().starts_with('.')); } #[cfg(windows)] From 8f30f1d248744dd5260b256a48205a41b207d889 Mon Sep 17 00:00:00 2001 From: Diego Magdaleno Date: Sat, 19 Dec 2020 09:25:12 -0600 Subject: [PATCH 11/11] ls: Fix the rust formatting in the new hidden functions --- src/uu/ls/src/ls.rs | 4 ++-- tests/by-util/test_ls.rs | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index e48d0c0dc5a..a2f8cab95b1 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -259,12 +259,12 @@ fn sort_entries(entries: &mut Vec, options: &getopts::Matches) { fn is_hidden(file_path: &DirEntry) -> std::io::Result { let metadata = fs::metadata(file_path.path())?; let attr = metadata.file_attributes(); - return Ok(((attr & 0x2) > 0) || file_path.file_name().to_string_lossy().starts_with('.')); + Ok(((attr & 0x2) > 0) || file_path.file_name().to_string_lossy().starts_with('.')) } #[cfg(unix)] fn is_hidden(file_path: &DirEntry) -> std::io::Result { - return Ok(file_path.file_name().to_string_lossy().starts_with('.')); + Ok(file_path.file_name().to_string_lossy().starts_with('.')) } #[cfg(windows)] diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 4ed0b947b8a..4dc4168de9e 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -319,7 +319,13 @@ fn test_ls_hidden_windows() { let file = "hiddenWindowsFileNoDot"; at.touch(file); // hide the file - scene.cmd("attrib").arg("+h").arg("+S").arg("+r").arg(file).run(); + scene + .cmd("attrib") + .arg("+h") + .arg("+S") + .arg("+r") + .arg(file) + .run(); let result = scene.ucmd().run(); println!("stderr = {:?}", result.stderr); println!("stdout = {:?}", result.stdout);