@@ -10,7 +10,7 @@ use std::collections::{HashMap, HashSet};
1010#[ cfg( not( windows) ) ]
1111use std:: ffi:: CString ;
1212use std:: ffi:: OsString ;
13- use std:: fs:: { self , File , Metadata , OpenOptions , Permissions } ;
13+ use std:: fs:: { self , Metadata , OpenOptions , Permissions } ;
1414use std:: io;
1515#[ cfg( unix) ]
1616use std:: os:: unix:: ffi:: OsStrExt ;
@@ -1963,6 +1963,7 @@ fn print_paths(parents: bool, source: &Path, dest: &Path) {
19631963///
19641964/// * `Ok(())` - The file was copied successfully.
19651965/// * `Err(CopyError)` - An error occurred while copying the file.
1966+ #[ allow( clippy:: too_many_arguments) ]
19661967fn handle_copy_mode (
19671968 source : & Path ,
19681969 dest : & Path ,
@@ -1971,15 +1972,10 @@ fn handle_copy_mode(
19711972 source_metadata : & Metadata ,
19721973 symlinked_files : & mut HashSet < FileInformation > ,
19731974 source_in_command_line : bool ,
1975+ source_is_fifo : bool ,
1976+ #[ cfg( unix) ] source_is_stream : bool ,
19741977) -> CopyResult < ( ) > {
1975- let source_file_type = source_metadata. file_type ( ) ;
1976-
1977- let source_is_symlink = source_file_type. is_symlink ( ) ;
1978-
1979- #[ cfg( unix) ]
1980- let source_is_fifo = source_file_type. is_fifo ( ) ;
1981- #[ cfg( not( unix) ) ]
1982- let source_is_fifo = false ;
1978+ let source_is_symlink = source_metadata. is_symlink ( ) ;
19831979
19841980 match options. copy_mode {
19851981 CopyMode :: Link => {
@@ -2016,6 +2012,8 @@ fn handle_copy_mode(
20162012 source_is_symlink,
20172013 source_is_fifo,
20182014 symlinked_files,
2015+ #[ cfg( unix) ]
2016+ source_is_stream,
20192017 ) ?;
20202018 }
20212019 CopyMode :: SymLink => {
@@ -2036,6 +2034,8 @@ fn handle_copy_mode(
20362034 source_is_symlink,
20372035 source_is_fifo,
20382036 symlinked_files,
2037+ #[ cfg( unix) ]
2038+ source_is_stream,
20392039 ) ?;
20402040 }
20412041 update_control:: UpdateMode :: ReplaceNone => {
@@ -2066,6 +2066,8 @@ fn handle_copy_mode(
20662066 source_is_symlink,
20672067 source_is_fifo,
20682068 symlinked_files,
2069+ #[ cfg( unix) ]
2070+ source_is_stream,
20692071 ) ?;
20702072 }
20712073 }
@@ -2079,6 +2081,8 @@ fn handle_copy_mode(
20792081 source_is_symlink,
20802082 source_is_fifo,
20812083 symlinked_files,
2084+ #[ cfg( unix) ]
2085+ source_is_stream,
20822086 ) ?;
20832087 }
20842088 }
@@ -2305,6 +2309,18 @@ fn copy_file(
23052309
23062310 let dest_permissions = calculate_dest_permissions ( dest, & source_metadata, options, context) ?;
23072311
2312+ #[ cfg( unix) ]
2313+ let source_is_fifo = source_metadata. file_type ( ) . is_fifo ( ) ;
2314+ #[ cfg( not( unix) ) ]
2315+ let source_is_fifo = false ;
2316+
2317+ #[ cfg( unix) ]
2318+ let source_is_stream = source_is_fifo
2319+ || source_metadata. file_type ( ) . is_char_device ( )
2320+ || source_metadata. file_type ( ) . is_block_device ( ) ;
2321+ #[ cfg( not( unix) ) ]
2322+ let source_is_stream = false ;
2323+
23082324 handle_copy_mode (
23092325 source,
23102326 dest,
@@ -2313,6 +2329,9 @@ fn copy_file(
23132329 & source_metadata,
23142330 symlinked_files,
23152331 source_in_command_line,
2332+ source_is_fifo,
2333+ #[ cfg( unix) ]
2334+ source_is_stream,
23162335 ) ?;
23172336
23182337 // TODO: implement something similar to gnu's lchown
@@ -2328,8 +2347,16 @@ fn copy_file(
23282347
23292348 if options. dereference ( source_in_command_line) {
23302349 if let Ok ( src) = canonicalize ( source, MissingHandling :: Normal , ResolveMode :: Physical ) {
2331- copy_attributes ( & src, dest, & options. attributes ) ?;
2350+ if src. exists ( ) {
2351+ copy_attributes ( & src, dest, & options. attributes ) ?;
2352+ }
23322353 }
2354+ } else if source_is_stream && source. exists ( ) {
2355+ // Some stream files may not exist after we have copied it,
2356+ // like anonymous pipes. Thus, we can't really copy its
2357+ // attributes. However, this is already handled in the stream
2358+ // copy function (see `copy_stream` under platform/linux.rs).
2359+ copy_attributes ( source, dest, & options. attributes ) ?;
23332360 } else {
23342361 copy_attributes ( source, dest, & options. attributes ) ?;
23352362 }
@@ -2393,6 +2420,7 @@ fn handle_no_preserve_mode(options: &Options, org_mode: u32) -> u32 {
23932420
23942421/// Copy the file from `source` to `dest` either using the normal `fs::copy` or a
23952422/// copy-on-write scheme if --reflink is specified and the filesystem supports it.
2423+ #[ allow( clippy:: too_many_arguments) ]
23962424fn copy_helper (
23972425 source : & Path ,
23982426 dest : & Path ,
@@ -2401,6 +2429,7 @@ fn copy_helper(
24012429 source_is_symlink : bool ,
24022430 source_is_fifo : bool ,
24032431 symlinked_files : & mut HashSet < FileInformation > ,
2432+ #[ cfg( unix) ] source_is_stream : bool ,
24042433) -> CopyResult < ( ) > {
24052434 if options. parents {
24062435 let parent = dest. parent ( ) . unwrap_or ( dest) ;
@@ -2411,12 +2440,7 @@ fn copy_helper(
24112440 return Err ( Error :: NotADirectory ( dest. to_path_buf ( ) ) ) ;
24122441 }
24132442
2414- if source. as_os_str ( ) == "/dev/null" {
2415- /* workaround a limitation of fs::copy
2416- * https://github.com/rust-lang/rust/issues/79390
2417- */
2418- File :: create ( dest) . context ( dest. display ( ) . to_string ( ) ) ?;
2419- } else if source_is_fifo && options. recursive && !options. copy_contents {
2443+ if source_is_fifo && options. recursive && !options. copy_contents {
24202444 #[ cfg( unix) ]
24212445 copy_fifo ( dest, options. overwrite , options. debug ) ?;
24222446 } else if source_is_symlink {
@@ -2428,8 +2452,10 @@ fn copy_helper(
24282452 options. reflink_mode ,
24292453 options. sparse_mode ,
24302454 context,
2431- #[ cfg( any ( target_os = "linux" , target_os = "android" , target_os = "macos" ) ) ]
2455+ #[ cfg( unix ) ]
24322456 source_is_fifo,
2457+ #[ cfg( unix) ]
2458+ source_is_stream,
24332459 ) ?;
24342460
24352461 if !options. attributes_only && options. debug {
0 commit comments