88use clap:: { Arg , ArgAction , Command , builder:: ValueParser , parser:: ValueSource } ;
99use std:: ffi:: { OsStr , OsString } ;
1010use std:: fs:: { self , Metadata } ;
11+ use std:: io:: { IsTerminal , stdin} ;
1112use std:: ops:: BitOr ;
1213#[ cfg( not( windows) ) ]
1314use std:: os:: unix:: ffi:: OsStrExt ;
@@ -68,6 +69,25 @@ pub struct Options {
6869 pub dir : bool ,
6970 /// `-v`, `--verbose`
7071 pub verbose : bool ,
72+ #[ doc( hidden) ]
73+ /// `---presume-input-tty`
74+ /// Always use `None`; GNU flag for testing use only
75+ pub __presume_input_tty : Option < bool > ,
76+ }
77+
78+ impl Default for Options {
79+ fn default ( ) -> Self {
80+ Self {
81+ force : false ,
82+ interactive : InteractiveMode :: PromptProtected ,
83+ one_fs : false ,
84+ preserve_root : true ,
85+ recursive : false ,
86+ dir : false ,
87+ verbose : false ,
88+ __presume_input_tty : None ,
89+ }
90+ }
7191}
7292
7393const ABOUT : & str = help_about ! ( "rm.md" ) ;
@@ -145,6 +165,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
145165 recursive : matches. get_flag ( OPT_RECURSIVE ) ,
146166 dir : matches. get_flag ( OPT_DIR ) ,
147167 verbose : matches. get_flag ( OPT_VERBOSE ) ,
168+ __presume_input_tty : if matches. get_flag ( PRESUME_INPUT_TTY ) {
169+ Some ( true )
170+ } else {
171+ None
172+ } ,
148173 } ;
149174 if options. interactive == InteractiveMode :: Once && ( options. recursive || files. len ( ) > 3 ) {
150175 let msg: String = format ! (
@@ -608,40 +633,45 @@ fn prompt_file(path: &Path, options: &Options) -> bool {
608633 prompt_yes ! ( "remove file {}?" , path. quote( ) )
609634 } ;
610635 }
611- prompt_file_permission_readonly ( path)
636+ prompt_file_permission_readonly ( path, options )
612637}
613638
614- fn prompt_file_permission_readonly ( path : & Path ) -> bool {
615- match fs:: metadata ( path) {
616- Ok ( _) if is_writable ( path) => true ,
617- Ok ( metadata) if metadata. len ( ) == 0 => prompt_yes ! (
639+ fn prompt_file_permission_readonly ( path : & Path , options : & Options ) -> bool {
640+ let stdin_ok = options. __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
641+ match ( stdin_ok, fs:: metadata ( path) , options. interactive ) {
642+ ( false , _, InteractiveMode :: PromptProtected ) => true ,
643+ ( _, Ok ( _) , _) if is_writable ( path) => true ,
644+ ( _, Ok ( metadata) , _) if metadata. len ( ) == 0 => prompt_yes ! (
618645 "remove write-protected regular empty file {}?" ,
619646 path. quote( )
620647 ) ,
621648 _ => prompt_yes ! ( "remove write-protected regular file {}?" , path. quote( ) ) ,
622649 }
623650}
624651
625- // For directories finding if they are writable or not is a hassle. In Unix we can use the built-in rust crate to to check mode bits. But other os don't have something similar afaik
652+ // For directories finding if they are writable or not is a hassle. In Unix we can use the built-in rust crate to check mode bits. But other os don't have something similar afaik
626653// Most cases are covered by keep eye out for edge cases
627654#[ cfg( unix) ]
628655fn handle_writable_directory ( path : & Path , options : & Options , metadata : & Metadata ) -> bool {
656+ let stdin_ok = options. __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
629657 match (
658+ stdin_ok,
630659 is_readable_metadata ( metadata) ,
631660 is_writable_metadata ( metadata) ,
632661 options. interactive ,
633662 ) {
634- ( false , false , _) => prompt_yes ! (
663+ ( false , _, _, InteractiveMode :: PromptProtected ) => true ,
664+ ( _, false , false , _) => prompt_yes ! (
635665 "attempt removal of inaccessible directory {}?" ,
636666 path. quote( )
637667 ) ,
638- ( false , true , InteractiveMode :: Always ) => prompt_yes ! (
668+ ( _ , false , true , InteractiveMode :: Always ) => prompt_yes ! (
639669 "attempt removal of inaccessible directory {}?" ,
640670 path. quote( )
641671 ) ,
642- ( true , false , _) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
643- ( _, _, InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path. quote( ) ) ,
644- ( _, _, _) => true ,
672+ ( _ , true , false , _) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
673+ ( _, _, _ , InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path. quote( ) ) ,
674+ ( _, _, _, _ ) => true ,
645675 }
646676}
647677
@@ -666,12 +696,12 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata
666696 use std:: os:: windows:: prelude:: MetadataExt ;
667697 use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_ATTRIBUTE_READONLY ;
668698 let not_user_writable = ( metadata. file_attributes ( ) & FILE_ATTRIBUTE_READONLY ) != 0 ;
669- if not_user_writable {
670- prompt_yes ! ( "remove write-protected directory {}?" , path . quote ( ) )
671- } else if options . interactive == InteractiveMode :: Always {
672- prompt_yes ! ( "remove directory {}?" , path. quote( ) )
673- } else {
674- true
699+ let stdin_ok = options . __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
700+ match ( stdin_ok , not_user_writable , options . interactive ) {
701+ ( false , _ , InteractiveMode :: PromptProtected ) => true ,
702+ ( _ , true , _ ) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
703+ ( _ , _ , InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path . quote ( ) ) ,
704+ ( _ , _ , _ ) => true ,
675705 }
676706}
677707
0 commit comments