From 660f1fcbe89c52e19f9f0ec0f1aff00784ab1aab Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 3 Jun 2023 11:16:50 -0700 Subject: [PATCH] Foundation: support file system representation for long paths This adjusts the file system representation accessor for a URL to support paths beyond `MAX_PATH`. We do not know what the use of the file system representation is, so we cannot provide the NT style path (`\\?\`-prefixed). Rather than using the filled in buffer, resolve the URL and then build the complete path copying that into a newly allocated buffer. This ensures that we always have sufficient space for the path without having to grow the buffer. Linux gets away with the current implementation by setting the `PATH_MAX` to page size (4096). There may be some value in using the single implementation across the different platforms, but this will allow the Windows path to make progress even if it diverges from the reference implementation. The issue was identified by the DocC test suite which quickly exceeds the length. --- Sources/Foundation/NSURL.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Sources/Foundation/NSURL.swift b/Sources/Foundation/NSURL.swift index a64b825b2c..e1b2e27fba 100644 --- a/Sources/Foundation/NSURL.swift +++ b/Sources/Foundation/NSURL.swift @@ -481,12 +481,16 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { // Memory leak. See https://github.com/apple/swift-corelibs-foundation/blob/master/Docs/Issues.md open var fileSystemRepresentation: UnsafePointer { - #if os(Windows) - let bufSize = Int(MAX_PATH + 1) + if let resolved = CFURLCopyAbsoluteURL(_cfObject), + let representation = CFURLCopyFileSystemPath(resolved, kCFURLWindowsPathStyle)?._swiftObject { + let buffer = UnsafeMutablePointer.allocate(capacity: representation.count + 1) + representation.withCString { buffer.initialize(from: $0, count: representation.count + 1) } + buffer[representation.count] = 0 + return UnsafePointer(buffer) + } #else let bufSize = Int(PATH_MAX + 1) -#endif let _fsrBuffer = UnsafeMutablePointer.allocate(capacity: bufSize) _fsrBuffer.initialize(repeating: 0, count: bufSize) @@ -494,6 +498,7 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { if getFileSystemRepresentation(_fsrBuffer, maxLength: bufSize) { return UnsafePointer(_fsrBuffer) } +#endif // FIXME: This used to return nil, but the corresponding Darwin // implementation is marked as non-nullable.