-
Notifications
You must be signed in to change notification settings - Fork 189
Fix Windows symlink handling in FileManager APIs #858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Windows symlink handling in FileManager APIs #858
Conversation
@swift-ci please test |
var ExtendedParameters: COPYFILE2_EXTENDED_PARAMETERS = .init() | ||
ExtendedParameters.dwSize = DWORD(MemoryLayout<COPYFILE2_EXTENDED_PARAMETERS>.size) | ||
ExtendedParameters.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS | COPY_FILE_COPY_SYMLINK | COPY_FILE_NO_BUFFERING | COPY_FILE_OPEN_AND_COPY_REPARSE_POINT | ||
ExtendedParameters.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS | COPY_FILE_NO_BUFFERING | ||
|
||
if FAILED(CopyFile2(pwszSource, pwszDestination, &ExtendedParameters)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As @jakepetroules mentioned in the GitHub issue - it seems there may be an issue with CopyFile2
itself here. I was unable to figure out the issue, so instead we now just handle symlink logic separately by reading the symlink's destination and creating a new symlink at the copy destination (which is what swift-corelibs-foundation roughly did)
Sources/FoundationEssentials/FileManager/FileManager+Basics.swift
Outdated
Show resolved
Hide resolved
@swift-ci please test |
@@ -817,7 +817,16 @@ enum _FileOperations { | |||
guard delegate.shouldPerformOnItemAtPath(src, to: dst) else { return } | |||
|
|||
try dst.withNTPathRepresentation { pwszDestination in | |||
if faAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY { | |||
// Check for reparse points first because symlinks to directories are reported as both reparse points and directories, and we should copy the symlink not the contents of the linked directory | |||
if faAttributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a non-symlinked directory happen to satisfy this constraint as well, and is that the desired behavior? By reading at this code, I'm not sure if fileManager.createSymbolicLink
would succeed since it's not a symlink. And if it fails, we'd throw
instead of proceeding to copy the content of the directory. Is that ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah plain directories won't have this flag set, but other types of reparse points that aren't supported by destinationOfSymbolicLink
would likely fail here - I think we can address that later since most of the FileManager
code in general likely doesn't do well with other types of reparse points
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a question, but I'm not sure if that's really a supported scenario. I don't mind addressing it later if that turns out to be an issue.
* Fix Windows symlink handling in FileManager APIs * Address feedback
* Fix Windows symlink handling in FileManager APIs * Address feedback
While getting SCL-F tests up and running on Windows, I noticed that those tests expose a handful of behavioral changes that swift-foundation made compared to swift-corelibs-foundation specifically around handling symlinks on Windows. In particular:
contentsEqual(atPath:andPath:)
would compare contents at the destination of symlinks rather than at the symlinks themselvescopyItem(atPath:toPath:)
would fail when copying symlinkscopyItem(atPath:toPath:)
would follow symlinks to directories and copy the directory contents rather than copying the symlinks themselvesThis PR addresses these issues and adds a handful of unit tests to validate all of these behaviors.
Resolves #845