Skip to content

Commit 11b0dbc

Browse files
committedJun 4, 2023
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.
1 parent 1e50a03 commit 11b0dbc

File tree

1 file changed

+8
-3
lines changed

1 file changed

+8
-3
lines changed
 

‎Sources/Foundation/NSURL.swift

+8-3
Original file line numberDiff line numberDiff line change
@@ -481,19 +481,24 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying {
481481

482482
// Memory leak. See https://github.com/apple/swift-corelibs-foundation/blob/master/Docs/Issues.md
483483
open var fileSystemRepresentation: UnsafePointer<Int8> {
484-
485484
#if os(Windows)
486-
let bufSize = Int(MAX_PATH + 1)
485+
if let resolved = CFURLCopyAbsoluteURL(_cfObject),
486+
let representation = CFURLCopyFileSystemPath(resolved, kCFURLWindowsPathStyle)?._swiftObject {
487+
let buffer = UnsafeMutablePointer<Int8>.allocate(capacity: representation.count + 1)
488+
representation.withCString { buffer.initialize(from: $0, count: representation.count + 1) }
489+
buffer[representation.count] = 0
490+
return UnsafePointer(buffer)
491+
}
487492
#else
488493
let bufSize = Int(PATH_MAX + 1)
489-
#endif
490494

491495
let _fsrBuffer = UnsafeMutablePointer<Int8>.allocate(capacity: bufSize)
492496
_fsrBuffer.initialize(repeating: 0, count: bufSize)
493497

494498
if getFileSystemRepresentation(_fsrBuffer, maxLength: bufSize) {
495499
return UnsafePointer(_fsrBuffer)
496500
}
501+
#endif
497502

498503
// FIXME: This used to return nil, but the corresponding Darwin
499504
// implementation is marked as non-nullable.

0 commit comments

Comments
 (0)