For File.Copy on macOS we're currently doing the following:
| returnfcopyfile(inFd, outFd, NULL, COPYFILE_ALL) ==0 ? 0 : -1; |
If we instead use
copyfile() we can use the
COPYFILE_CLONE option (with the existing
COPYFILE_ALL obviously, which I think the clone option may include all of the flags of anyway), which allows the file to be instantly copied on supported filesystems, and falls back to exactly the same implementation when it's not available (note - this behaves identically (except with symlinks (ie. this copies the symlink itself I think) and when the destination exists, which we can special case), it just allows APFS to immediately set the data location to the existing file, and when it's updated it will be create a copy since APFS is a copy-on-write filesystem). This is obviously much faster (I tested it on a hard drive with a 30GB file and it copied instantly).
We can implement that in this file:
| publicstaticvoidCopyFile(stringsourceFullPath,stringdestFullPath,booloverwrite) |
by splitting the OSX-like platforms code, like we have with the code that sets the creation date.
We should be able to implement it with effectively the same behaviour as whatever the current behaviour is with relative ease. Note: apps like finder clone files in this way.
I'd like to implement this in a PR if approved (ideally by .NET 8).
For
File.Copyon macOS we're currently doing the following:runtime/src/native/libs/System.Native/pal_io.c
Line 1257 in d320fd9
If we instead use
copyfile()we can use theCOPYFILE_CLONEoption (with the existingCOPYFILE_ALLobviously, which I think the clone option may include all of the flags of anyway), which allows the file to be instantly copied on supported filesystems, and falls back to exactly the same implementation when it's not available (note - this behaves identically (except with symlinks (ie. this copies the symlink itself I think) and when the destination exists, which we can special case), it just allows APFS to immediately set the data location to the existing file, and when it's updated it will be create a copy since APFS is a copy-on-write filesystem). This is obviously much faster (I tested it on a hard drive with a 30GB file and it copied instantly).We can implement that in this file:
runtime/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs
Line 31 in 21e9913
by splitting the OSX-like platforms code, like we have with the code that sets the creation date.
We should be able to implement it with effectively the same behaviour as whatever the current behaviour is with relative ease. Note: apps like finder clone files in this way.
I'd like to implement this in a PR if approved (ideally by .NET 8).