@@ -18,6 +18,7 @@ mod sys;
1818
1919use std:: fs;
2020use std:: io;
21+ use std:: io:: ErrorKind ;
2122use std:: path:: Path ;
2223
2324/// Copies a file using COW semantics.
@@ -93,6 +94,8 @@ pub fn reflink(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
9394///
9495/// If the function copied a file, the return value will be `Ok(Some(written))`.
9596///
97+ /// If target file already exists, operation fails with [`ErrorKind::AlreadyExists`].
98+ ///
9699/// ```rust
97100/// match reflink_copy::reflink_or_copy("src.txt", "dest.txt") {
98101/// Ok(None) => println!("file has been reflinked"),
@@ -116,13 +119,20 @@ pub fn reflink_or_copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Resu
116119 tracing_attributes:: instrument( name = "reflink_or_copy" )
117120 ) ]
118121 fn inner ( from : & Path , to : & Path ) -> io:: Result < Option < u64 > > {
119- if let Err ( _err) = sys:: reflink ( from, to) {
122+ if let Err ( err) = sys:: reflink ( from, to) {
123+ match err. kind ( ) {
124+ ErrorKind :: NotFound | ErrorKind :: PermissionDenied | ErrorKind :: AlreadyExists => {
125+ return Err ( err) ;
126+ }
127+ _ => { }
128+ }
129+
120130 #[ cfg( feature = "tracing" ) ]
121- tracing:: warn!( ?_err , "Failed to reflink, fallback to fs::copy" ) ;
131+ tracing:: warn!( ?err , "Failed to reflink, fallback to fs::copy" ) ;
122132
123133 fs:: copy ( from, to) . map ( Some ) . map_err ( |err| {
124134 // Both regular files and symlinks to regular files can be copied, so unlike
125- // `reflink` we don't want to report invalid input on both files and and symlinks
135+ // `reflink` we don't want to report invalid input on both files and symlinks
126136 if from. is_file ( ) {
127137 err
128138 } else {
0 commit comments