@@ -10,6 +10,7 @@ use std::collections::{HashMap, HashSet};
1010use std:: env;
1111#[ cfg( not( windows) ) ]
1212use std:: ffi:: CString ;
13+ use std:: ffi:: OsString ;
1314use std:: fs:: { self , File , Metadata , OpenOptions , Permissions } ;
1415use std:: io;
1516#[ cfg( unix) ]
@@ -692,7 +693,7 @@ pub fn uu_app() -> Command {
692693 Arg :: new ( options:: PATHS )
693694 . action ( ArgAction :: Append )
694695 . value_hint ( clap:: ValueHint :: AnyPath )
695- . value_parser ( ValueParser :: path_buf ( ) ) ,
696+ . value_parser ( clap :: value_parser! ( OsString ) ) ,
696697 )
697698}
698699
@@ -722,8 +723,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
722723 }
723724
724725 let paths: Vec < PathBuf > = matches
725- . remove_many :: < PathBuf > ( options:: PATHS )
726- . map ( |v| v. collect ( ) )
726+ . remove_many :: < OsString > ( options:: PATHS )
727+ . map ( |v| {
728+ v. map ( |w| PathBuf :: from ( w) )
729+ . collect ( )
730+ } )
727731 . unwrap_or_default ( ) ;
728732
729733 let ( sources, target) = parse_path_args ( paths, & options) ?;
@@ -1134,7 +1138,24 @@ fn parse_path_args(
11341138 }
11351139 }
11361140
1137- Ok ( ( paths, target) )
1141+ // If the path exists and is valid keep it in the argument list.
1142+ // Exception for symlinks as they are a bit more tricky to handle
1143+ // and there's logic further down the execution to handle them.
1144+ let ( okpaths, invalidpaths) : ( Vec < _ > , Vec < _ > ) = paths
1145+ . into_iter ( )
1146+ . partition ( |p| p. is_symlink ( ) || p. exists ( ) ) ;
1147+
1148+ if !invalidpaths. is_empty ( ) {
1149+ for p in invalidpaths. into_iter ( ) {
1150+ eprintln ! (
1151+ "cp: cannot stat '{}': No such file or directory" ,
1152+ p. display( )
1153+ ) ;
1154+ }
1155+ set_exit_code ( EXIT_ERR ) ;
1156+ }
1157+
1158+ Ok ( ( okpaths, target) )
11381159}
11391160
11401161/// When handling errors, we don't always want to show them to the user. This function handles that.
0 commit comments