Skip to content

Commit 3397c2b

Browse files
compnerdaciidgh
authored andcommitted
Basic: correctly identify paths as absolute/relative on Windows
Use the sanctioned `PathIsRelativeW` API from Windows to handle the absolute/relative path checking. Use `Foundation` for converting paths to the canonicalized representation first.
1 parent 6d53a58 commit 3397c2b

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

Sources/TSCBasic/Path.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
#if os(Windows)
1111
import Foundation
12+
import WinSDK
1213
#endif
1314

1415
/// Represents an absolute file system path, independently of what (or whether
@@ -103,6 +104,16 @@ public struct AbsolutePath: Hashable {
103104

104105
/// Convenience initializer that verifies that the path is absolute.
105106
public init(validating path: String) throws {
107+
#if os(Windows)
108+
let fsr: UnsafePointer<Int8> = path.fileSystemRepresentation
109+
defer { fsr.deallocate() }
110+
111+
let realpath = String(cString: fsr)
112+
if realpath.withCString(encodedAs: UTF16.self, PathIsRelativeW) {
113+
throw PathValidationError.invalidAbsolutePath(path)
114+
}
115+
self.init(path)
116+
#else
106117
switch path.first {
107118
case "/":
108119
self.init(path)
@@ -111,6 +122,7 @@ public struct AbsolutePath: Hashable {
111122
default:
112123
throw PathValidationError.invalidAbsolutePath(path)
113124
}
125+
#endif
114126
}
115127

116128
/// Directory component. An absolute path always has a non-empty directory
@@ -256,12 +268,23 @@ public struct RelativePath: Hashable {
256268

257269
/// Convenience initializer that verifies that the path is relative.
258270
public init(validating path: String) throws {
271+
#if os(Windows)
272+
let fsr: UnsafePointer<Int8> = path.fileSystemRepresentation
273+
defer { fsr.deallocate() }
274+
275+
let realpath: String = String(cString: fsr)
276+
if !realpath.withCString(encodedAs: UTF16.self, PathIsRelativeW) {
277+
throw PathValidationError.invalidRelativePath(path)
278+
}
279+
self.init(path)
280+
#else
259281
switch path.first {
260282
case "/", "~":
261283
throw PathValidationError.invalidRelativePath(path)
262284
default:
263285
self.init(path)
264286
}
287+
#endif
265288
}
266289

267290
/// Directory component. For a relative path without any path separators,

0 commit comments

Comments
 (0)