Skip to content

Commit 81d78be

Browse files
committed
Fix Windows build
1 parent 915070e commit 81d78be

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

Sources/System/FileOperations.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,23 @@ extension FileDescriptor {
3131
permissions: FilePermissions? = nil,
3232
retryOnInterrupt: Bool = true
3333
) throws -> FileDescriptor {
34+
#if !os(Windows)
3435
try path.withCString {
3536
try FileDescriptor.open(
3637
$0, mode, options: options, permissions: permissions, retryOnInterrupt: retryOnInterrupt)
3738
}
39+
#else
40+
try path.withPlatformString {
41+
try FileDescriptor.open(
42+
$0, mode, options: options, permissions: permissions, retryOnInterrupt: retryOnInterrupt)
43+
}
44+
#endif
3845
}
3946

47+
#if !os(Windows)
48+
// On Darwin, `CInterop.PlatformChar` is less available than
49+
// `FileDescriptor.open`, so we need to use `CChar` instead.
50+
4051
/// Opens or creates a file for reading or writing.
4152
///
4253
/// - Parameters:
@@ -83,6 +94,54 @@ extension FileDescriptor {
8394
}
8495
return descOrError.map { FileDescriptor(rawValue: $0) }
8596
}
97+
#else
98+
/// Opens or creates a file for reading or writing.
99+
///
100+
/// - Parameters:
101+
/// - path: The location of the file to open.
102+
/// - mode: The read and write access to use.
103+
/// - options: The behavior for opening the file.
104+
/// - permissions: The file permissions to use for created files.
105+
/// - retryOnInterrupt: Whether to retry the open operation
106+
/// if it throws ``Errno/interrupted``.
107+
/// The default is `true`.
108+
/// Pass `false` to try only once and throw an error upon interruption.
109+
/// - Returns: A file descriptor for the open file
110+
///
111+
/// The corresponding C function is `open`.
112+
@_alwaysEmitIntoClient
113+
public static func open(
114+
_ path: UnsafePointer<CInterop.PlatformChar>,
115+
_ mode: FileDescriptor.AccessMode,
116+
options: FileDescriptor.OpenOptions = FileDescriptor.OpenOptions(),
117+
permissions: FilePermissions? = nil,
118+
retryOnInterrupt: Bool = true
119+
) throws -> FileDescriptor {
120+
try FileDescriptor._open(
121+
path, mode, options: options, permissions: permissions, retryOnInterrupt: retryOnInterrupt
122+
).get()
123+
}
124+
125+
@usableFromInline
126+
internal static func _open(
127+
_ path: UnsafePointer<CInterop.PlatformChar>,
128+
_ mode: FileDescriptor.AccessMode,
129+
options: FileDescriptor.OpenOptions,
130+
permissions: FilePermissions?,
131+
retryOnInterrupt: Bool
132+
) -> Result<FileDescriptor, Errno> {
133+
let oFlag = mode.rawValue | options.rawValue
134+
let descOrError: Result<CInt, Errno> = valueOrErrno(retryOnInterrupt: retryOnInterrupt) {
135+
if let permissions = permissions {
136+
return system_open(path, oFlag, permissions.rawValue)
137+
}
138+
precondition(!options.contains(.create),
139+
"Create must be given permissions")
140+
return system_open(path, oFlag)
141+
}
142+
return descOrError.map { FileDescriptor(rawValue: $0) }
143+
}
144+
#endif
86145

87146
/// Deletes a file descriptor.
88147
///

Sources/System/FilePath/FilePathString.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ extension FilePath {
2020
self.init(_platformString: platformString)
2121
}
2222

23-
#if !os(Windows) // Availability workaround
23+
#if !os(Windows)
24+
// Note: This function should have been opaque, but it shipped as
25+
// `@_alwaysEmitIntoClient` in macOS 12/iOS 15, and now it is stuck
26+
// this way forever. (Or until the language provides a way for us
27+
// to declare separate availability for a function's exported symbol
28+
// and its inlinable body.)
29+
2430
/// Calls the given closure with a pointer to the contents of the file path,
2531
/// represented as a null-terminated platform string.
2632
///
@@ -37,7 +43,6 @@ extension FilePath {
3743
public func withPlatformString<Result>(
3844
_ body: (UnsafePointer<CInterop.PlatformChar>) throws -> Result
3945
) rethrows -> Result {
40-
// For backwards deployment, call withCString if available.
4146
return try withCString(body)
4247
}
4348
#else
@@ -56,7 +61,6 @@ extension FilePath {
5661
public func withPlatformString<Result>(
5762
_ body: (UnsafePointer<CInterop.PlatformChar>) throws -> Result
5863
) rethrows -> Result {
59-
// For backwards deployment, call withCString if available.
6064
return try _withPlatformString(body)
6165
}
6266
#endif

0 commit comments

Comments
 (0)