@@ -19,10 +19,16 @@ use std::process::{exit, ExitCode};
1919// 1 means some differences were found,
2020// and 2 means trouble.
2121pub fn main ( opts : Peekable < ArgsOs > ) -> ExitCode {
22- let params = parse_params ( opts) . unwrap_or_else ( |error| {
22+ let mut params = parse_params ( opts) . unwrap_or_else ( |error| {
2323 eprintln ! ( "{error}" ) ;
2424 exit ( 2 ) ;
2525 } ) ;
26+ // diff - FILE with a directory on stdin => diff DIRECTORY/FILE FILE
27+ if params. from == "-" && params. to != "-" {
28+ if let Some ( from) = stdin_directory_entry ( & params. to ) {
29+ params. from = from;
30+ }
31+ }
2632 // if from and to are the same file, no need to perform any comparison
2733 let maybe_report_identical_files = || {
2834 if params. report_identical_files {
@@ -136,3 +142,34 @@ const BINARY_PROBE_LEN: usize = 16 * 1024;
136142fn is_binary ( content : & [ u8 ] ) -> bool {
137143 content[ ..content. len ( ) . min ( BINARY_PROBE_LEN ) ] . contains ( & 0 )
138144}
145+
146+ /// When standard input is a directory, returns the path of the entry in it
147+ /// that has the same name as `other`, provided `other` is not a directory.
148+ /// Entries are reached through `/dev/fd/0`, which only names the directory
149+ /// itself where it links to the open file, as with Linux procfs.
150+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
151+ fn stdin_directory_entry ( other : & OsString ) -> Option < OsString > {
152+ use std:: os:: fd:: AsFd ;
153+ use std:: path:: Path ;
154+
155+ let stdin_is_dir = io:: stdin ( )
156+ . as_fd ( )
157+ . try_clone_to_owned ( )
158+ . ok ( )
159+ . and_then ( |fd| fs:: File :: from ( fd) . metadata ( ) . ok ( ) )
160+ . is_some_and ( |metadata| metadata. is_dir ( ) ) ;
161+ let other = Path :: new ( other) ;
162+ if !stdin_is_dir || other. is_dir ( ) {
163+ return None ;
164+ }
165+ Some (
166+ Path :: new ( "/dev/fd/0" )
167+ . join ( other. file_name ( ) ?)
168+ . into_os_string ( ) ,
169+ )
170+ }
171+
172+ #[ cfg( not( any( target_os = "linux" , target_os = "android" ) ) ) ]
173+ fn stdin_directory_entry ( _other : & OsString ) -> Option < OsString > {
174+ None
175+ }
0 commit comments