@@ -12,6 +12,8 @@ use std::fs::{self, Metadata};
1212use std:: ops:: BitOr ;
1313#[ cfg( not( windows) ) ]
1414use std:: os:: unix:: ffi:: OsStrExt ;
15+ #[ cfg( unix) ]
16+ use std:: os:: unix:: fs:: PermissionsExt ;
1517use std:: path:: MAIN_SEPARATOR ;
1618use std:: path:: { Path , PathBuf } ;
1719use uucore:: display:: Quotable ;
@@ -328,6 +330,25 @@ pub fn remove(files: &[&OsStr], options: &Options) -> bool {
328330 had_err
329331}
330332
333+ /// Whether the given file or directory is writable.
334+ #[ cfg( unix) ]
335+ fn is_writable ( path : & Path ) -> bool {
336+ match std:: fs:: metadata ( path) {
337+ Err ( _) => false ,
338+ Ok ( metadata) => {
339+ let mode = metadata. permissions ( ) . mode ( ) ;
340+ ( mode & 0o200 ) > 0
341+ }
342+ }
343+ }
344+
345+ /// Whether the given file or directory is writable.
346+ #[ cfg( not( unix) ) ]
347+ fn is_writable ( _path : & Path ) -> bool {
348+ // TODO Not yet implemented.
349+ true
350+ }
351+
331352#[ allow( clippy:: cognitive_complexity) ]
332353fn handle_dir ( path : & Path , options : & Options ) -> bool {
333354 let mut had_err = false ;
@@ -515,7 +536,7 @@ fn prompt_file(path: &Path, options: &Options) -> bool {
515536 return true ;
516537 } ;
517538
518- if options. interactive == InteractiveMode :: Always && !metadata . permissions ( ) . readonly ( ) {
539+ if options. interactive == InteractiveMode :: Always && is_writable ( path ) {
519540 return if metadata. len ( ) == 0 {
520541 prompt_yes ! ( "remove regular empty file {}?" , path. quote( ) )
521542 } else {
@@ -527,7 +548,7 @@ fn prompt_file(path: &Path, options: &Options) -> bool {
527548
528549fn prompt_file_permission_readonly ( path : & Path ) -> bool {
529550 match fs:: metadata ( path) {
530- Ok ( metadata ) if !metadata . permissions ( ) . readonly ( ) => true ,
551+ Ok ( _ ) if is_writable ( path ) => true ,
531552 Ok ( metadata) if metadata. len ( ) == 0 => prompt_yes ! (
532553 "remove write-protected regular empty file {}?" ,
533554 path. quote( )
0 commit comments