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 ! (
@@ -611,40 +636,45 @@ fn prompt_file(path: &Path, options: &Options) -> bool {
611636 prompt_yes ! ( "remove file {}?" , path. quote( ) )
612637 } ;
613638 }
614- prompt_file_permission_readonly ( path)
639+ prompt_file_permission_readonly ( path, options )
615640}
616641
617- fn prompt_file_permission_readonly ( path : & Path ) -> bool {
618- match fs:: metadata ( path) {
619- Ok ( _) if is_writable ( path) => true ,
620- Ok ( metadata) if metadata. len ( ) == 0 => prompt_yes ! (
642+ fn prompt_file_permission_readonly ( path : & Path , options : & Options ) -> bool {
643+ let stdin_ok = options. __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
644+ match ( stdin_ok, fs:: metadata ( path) , options. interactive ) {
645+ ( false , _, InteractiveMode :: PromptProtected ) => true ,
646+ ( _, Ok ( _) , _) if is_writable ( path) => true ,
647+ ( _, Ok ( metadata) , _) if metadata. len ( ) == 0 => prompt_yes ! (
621648 "remove write-protected regular empty file {}?" ,
622649 path. quote( )
623650 ) ,
624651 _ => prompt_yes ! ( "remove write-protected regular file {}?" , path. quote( ) ) ,
625652 }
626653}
627654
628- // 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
655+ // 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
629656// Most cases are covered by keep eye out for edge cases
630657#[ cfg( unix) ]
631658fn handle_writable_directory ( path : & Path , options : & Options , metadata : & Metadata ) -> bool {
659+ let stdin_ok = options. __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
632660 match (
661+ stdin_ok,
633662 is_readable_metadata ( metadata) ,
634663 is_writable_metadata ( metadata) ,
635664 options. interactive ,
636665 ) {
637- ( false , false , _) => prompt_yes ! (
666+ ( false , _, _, InteractiveMode :: PromptProtected ) => true ,
667+ ( _, false , false , _) => prompt_yes ! (
638668 "attempt removal of inaccessible directory {}?" ,
639669 path. quote( )
640670 ) ,
641- ( false , true , InteractiveMode :: Always ) => prompt_yes ! (
671+ ( _ , false , true , InteractiveMode :: Always ) => prompt_yes ! (
642672 "attempt removal of inaccessible directory {}?" ,
643673 path. quote( )
644674 ) ,
645- ( true , false , _) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
646- ( _, _, InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path. quote( ) ) ,
647- ( _, _, _) => true ,
675+ ( _ , true , false , _) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
676+ ( _, _, _ , InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path. quote( ) ) ,
677+ ( _, _, _, _ ) => true ,
648678 }
649679}
650680
@@ -669,12 +699,12 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata
669699 use std:: os:: windows:: prelude:: MetadataExt ;
670700 use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_ATTRIBUTE_READONLY ;
671701 let not_user_writable = ( metadata. file_attributes ( ) & FILE_ATTRIBUTE_READONLY ) != 0 ;
672- if not_user_writable {
673- prompt_yes ! ( "remove write-protected directory {}?" , path . quote ( ) )
674- } else if options . interactive == InteractiveMode :: Always {
675- prompt_yes ! ( "remove directory {}?" , path. quote( ) )
676- } else {
677- true
702+ let stdin_ok = options . __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
703+ match ( stdin_ok , not_user_writable , options . interactive ) {
704+ ( false , _ , InteractiveMode :: PromptProtected ) => true ,
705+ ( _ , true , _ ) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
706+ ( _ , _ , InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path . quote ( ) ) ,
707+ ( _ , _ , _ ) => true ,
678708 }
679709}
680710
0 commit comments