@@ -24,9 +24,9 @@ use std::io::ErrorKind;
2424use std:: os:: unix:: fs:: OpenOptionsExt ;
2525use std:: path:: { Path , PathBuf } ;
2626use uucore:: display:: Quotable ;
27- use uucore:: error:: { FromIo , UResult , USimpleError } ;
27+ use uucore:: error:: { FromIo , UIoError , UResult , USimpleError } ;
2828use uucore:: format_usage;
29- #[ cfg( unix) ]
29+ #[ cfg( any ( unix, target_os = "macos" ) ) ]
3030use uucore:: libc;
3131use uucore:: parser:: shortcut_value_parser:: ShortcutValueParser ;
3232use uucore:: { show, translate} ;
@@ -482,38 +482,25 @@ fn touch_file(
482482 . open ( path) ;
483483
484484 if let Err ( e) = touched_file {
485- // It's better to take the negative approach here, but there's an issue with
486- // Rust's standard library when it comes to mapping certain OS errors to ErrorKind.
487- // Those map to ErrorKind::Uncategorized, which is currently marked 'unstable' .
488- // So, as a work-around, we look at raw_os_error for libc::ENXIO (6) directly on unix systems.
489- // We always ignore IsADirectory since directories are fair game to be touched.
490- # [ cfg ( unix ) ]
485+ // We have to check to see if the reason .open() failed above is something
486+ // that is fatal or something expected. The former is handled here, whereas
487+ // the latter is handled in update_times() .
488+ let err_good_cause = e . kind ( ) != ErrorKind :: IsADirectory ;
489+
490+ // For UNIX/MAC, we also have to check special files, like FIFOs.
491491 // If we can't unwrap a raw OS error, default it to 0 so that it's considered true
492492 // for the first Boolean condition.
493- let err_good_cause =
494- e. raw_os_error ( ) . unwrap_or ( 0 ) != libc:: ENXIO && e. kind ( ) != ErrorKind :: IsADirectory ;
495-
496- #[ cfg( not( unix) ) ]
497- let err_good_cause = e. kind ( ) != ErrorKind :: IsADirectory ;
493+ #[ cfg( any( unix, target_os = "macos" ) ) ]
494+ let err_good_cause = e. raw_os_error ( ) . unwrap_or ( 0 ) != libc:: ENXIO && err_good_cause;
498495
499- // Any errors that make it here are considered errors of file creation/opening, otherwise
500- // we let update_times() handle them.
496+ // err_good_cause indicates that the error is not one we should ignore
501497 if err_good_cause {
502- // Rust's e.kind().to_string() doesn't always give good descriptions for certain errors.
503- let err_str: String = match e. kind ( ) {
504- ErrorKind :: NotFound => "No such file or directory" . to_string ( ) ,
505- ErrorKind :: TooManyLinks => "Too many links" . to_string ( ) ,
506- ErrorKind :: PermissionDenied => "Permission denied" . to_string ( ) ,
507- ErrorKind :: QuotaExceeded => "Quota exceeded" . to_string ( ) ,
508- ErrorKind :: ReadOnlyFilesystem => "Read only file system" . to_string ( ) ,
509- _ => e. to_string ( ) ,
510- } ;
511498 return Err ( TouchError :: TouchFileError {
512499 path : path. to_owned ( ) ,
513500 index : 0 ,
514501 error : USimpleError :: new (
515502 1 ,
516- translate ! ( "touch-error-cannot-touch" , "filename" => path. quote( ) , "error" => err_str ) ,
503+ translate ! ( "touch-error-cannot-touch" , "filename" => path. quote( ) , "error" => UIoError :: from ( e ) ) ,
517504 ) ,
518505 } . into ( ) ) ;
519506 }
@@ -597,14 +584,14 @@ fn update_times(
597584 // but since it was removed to fix TOCTOU issues, we need to handle it here.
598585 if let Err ( ref e) = result {
599586 if opts. no_create && e. kind ( ) != ErrorKind :: NotADirectory {
600- #[ cfg( unix) ]
587+ #[ cfg( any ( unix, target_os = "macos" ) ) ]
601588 if e. raw_os_error ( ) != Some ( libc:: ELOOP ) {
602589 // ELOOP is returned when trying to stat a dangling symlink with -h/--no-dereference.
603590 // However, the ErrorKind is unstable in Rust, so we have to kind
604591 // of hack it like this.
605592 return Ok ( ( ) ) ;
606593 }
607- #[ cfg( not( unix) ) ]
594+ #[ cfg( not( any ( unix, target_os = "macos" ) ) ) ]
608595 return Ok ( ( ) ) ;
609596 }
610597 return result. map_err_context (
0 commit comments