@@ -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 ///
0 commit comments