8
8
use clap:: { Arg , ArgAction , Command , builder:: ValueParser , parser:: ValueSource } ;
9
9
use std:: ffi:: { OsStr , OsString } ;
10
10
use std:: fs:: { self , Metadata } ;
11
+ use std:: io:: { IsTerminal , stdin} ;
11
12
use std:: ops:: BitOr ;
12
13
#[ cfg( not( windows) ) ]
13
14
use std:: os:: unix:: ffi:: OsStrExt ;
@@ -68,6 +69,25 @@ pub struct Options {
68
69
pub dir : bool ,
69
70
/// `-v`, `--verbose`
70
71
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
+ }
71
91
}
72
92
73
93
const ABOUT : & str = help_about ! ( "rm.md" ) ;
@@ -145,6 +165,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
145
165
recursive : matches. get_flag ( OPT_RECURSIVE ) ,
146
166
dir : matches. get_flag ( OPT_DIR ) ,
147
167
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
+ } ,
148
173
} ;
149
174
if options. interactive == InteractiveMode :: Once && ( options. recursive || files. len ( ) > 3 ) {
150
175
let msg: String = format ! (
@@ -608,40 +633,45 @@ fn prompt_file(path: &Path, options: &Options) -> bool {
608
633
prompt_yes ! ( "remove file {}?" , path. quote( ) )
609
634
} ;
610
635
}
611
- prompt_file_permission_readonly ( path)
636
+ prompt_file_permission_readonly ( path, options )
612
637
}
613
638
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 ! (
618
645
"remove write-protected regular empty file {}?" ,
619
646
path. quote( )
620
647
) ,
621
648
_ => prompt_yes ! ( "remove write-protected regular file {}?" , path. quote( ) ) ,
622
649
}
623
650
}
624
651
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
626
653
// Most cases are covered by keep eye out for edge cases
627
654
#[ cfg( unix) ]
628
655
fn handle_writable_directory ( path : & Path , options : & Options , metadata : & Metadata ) -> bool {
656
+ let stdin_ok = options. __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
629
657
match (
658
+ stdin_ok,
630
659
is_readable_metadata ( metadata) ,
631
660
is_writable_metadata ( metadata) ,
632
661
options. interactive ,
633
662
) {
634
- ( false , false , _) => prompt_yes ! (
663
+ ( false , _, _, InteractiveMode :: PromptProtected ) => true ,
664
+ ( _, false , false , _) => prompt_yes ! (
635
665
"attempt removal of inaccessible directory {}?" ,
636
666
path. quote( )
637
667
) ,
638
- ( false , true , InteractiveMode :: Always ) => prompt_yes ! (
668
+ ( _ , false , true , InteractiveMode :: Always ) => prompt_yes ! (
639
669
"attempt removal of inaccessible directory {}?" ,
640
670
path. quote( )
641
671
) ,
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 ,
645
675
}
646
676
}
647
677
@@ -666,12 +696,12 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata
666
696
use std:: os:: windows:: prelude:: MetadataExt ;
667
697
use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_ATTRIBUTE_READONLY ;
668
698
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 ,
675
705
}
676
706
}
677
707
0 commit comments