Skip to content

Commit adf511f

Browse files
committed
Foundation: improve relative path computation for iteration on Windows
This partially corrects the relative path computation. We no longer fail to create the file system representation if it exceeds `MAX_PATH` due to the switch to `withUnsafeNTPath`. We will still fail to properly create the relative path if the paths are unrelated and if the relative path exceeds `MAX_PATH`. However, this still is an improvement over the status quo.
1 parent 04ddb8e commit adf511f

File tree

2 files changed

+15
-22
lines changed

2 files changed

+15
-22
lines changed

Sources/Foundation/FileManager+Win32.swift

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,23 +1075,24 @@ extension FileManager.NSPathDirectoryEnumerator {
10751075
internal func _nextObject() -> Any? {
10761076
guard let url = innerEnumerator.nextObject() as? URL else { return nil }
10771077

1078-
var relativePath: [WCHAR] = Array<WCHAR>(repeating: 0, count: Int(MAX_PATH))
1079-
1080-
guard baseURL._withUnsafeWideFileSystemRepresentation({ baseUrlFsr in
1081-
url._withUnsafeWideFileSystemRepresentation { urlFsr in
1082-
let fromAttrs = GetFileAttributesW(baseUrlFsr)
1083-
let toAttrs = GetFileAttributesW(urlFsr)
1084-
guard fromAttrs != INVALID_FILE_ATTRIBUTES, toAttrs != INVALID_FILE_ATTRIBUTES else {
1085-
return false
1078+
let path: String? = try? baseURL.withUnsafeNTPath { pwszBasePath in
1079+
let dwBaseAttrs = GetFileAttributesW(pwszBasePath)
1080+
if dwBaseAttrs == INVALID_FILE_ATTRIBUTES { return nil }
1081+
1082+
return try? url.withUnsafeNTPath { pwszPath in
1083+
let dwAttrs = GetFileAttributesW(pwszPath)
1084+
if dwAttrs == INVALID_FILE_ATTRIBUTES { return nil }
1085+
1086+
return withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(MAX_PATH)) {
1087+
guard PathRelativePathToW($0.baseAddress, pwszBasePath, dwBaseAttrs, pwszPath, dwAttrs) else { return nil }
1088+
// Drop the leading ".\" from the path
1089+
return String(decodingCString: $0.baseAddress!.advanced(by: 2), as: UTF16.self)
10861090
}
1087-
return PathRelativePathToW(&relativePath, baseUrlFsr, fromAttrs, urlFsr, toAttrs)
10881091
}
1089-
}) else { return nil }
1092+
}
10901093

1091-
let path = String(decodingCString: &relativePath, as: UTF16.self)
1092-
// Drop the leading ".\" from the path
1093-
_currentItemPath = String(path.dropFirst(2))
1094-
return _currentItemPath
1094+
_currentItemPath = path ?? _currentItemPath
1095+
return path
10951096
}
10961097

10971098
}

Sources/Foundation/URL.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -723,14 +723,6 @@ public struct URL : ReferenceConvertible, Equatable {
723723
return try block(fsRep)
724724
}
725725

726-
#if os(Windows)
727-
internal func _withUnsafeWideFileSystemRepresentation<ResultType>(_ block: (UnsafePointer<UInt16>?) throws -> ResultType) rethrows -> ResultType {
728-
let fsr: UnsafePointer<UInt16> = _url._wideFileSystemRepresentation
729-
defer { fsr.deallocate() }
730-
return try block(fsr)
731-
}
732-
#endif
733-
734726
// MARK: -
735727
// MARK: Path manipulation
736728

0 commit comments

Comments
 (0)