@@ -31,12 +31,70 @@ extension FileDescriptor {
3131 permissions: FilePermissions ? = nil ,
3232 retryOnInterrupt: Bool = true
3333 ) throws -> FileDescriptor {
34- try path. withPlatformString {
34+ #if !os(Windows)
35+ return try path. withCString {
3536 try FileDescriptor . open (
3637 $0, mode, options: options, permissions: permissions, retryOnInterrupt: retryOnInterrupt)
3738 }
39+ #else
40+ return try path. withPlatformString {
41+ try FileDescriptor . open (
42+ $0, mode, options: options, permissions: permissions, retryOnInterrupt: retryOnInterrupt)
43+ }
44+ #endif
45+ }
46+
47+ #if !os(Windows)
48+ // On Darwin, `CInterop.PlatformChar` is less available than
49+ // `FileDescriptor.open`, so we need to use `CChar` instead.
50+
51+ /// Opens or creates a file for reading or writing.
52+ ///
53+ /// - Parameters:
54+ /// - path: The location of the file to open.
55+ /// - mode: The read and write access to use.
56+ /// - options: The behavior for opening the file.
57+ /// - permissions: The file permissions to use for created files.
58+ /// - retryOnInterrupt: Whether to retry the open operation
59+ /// if it throws ``Errno/interrupted``.
60+ /// The default is `true`.
61+ /// Pass `false` to try only once and throw an error upon interruption.
62+ /// - Returns: A file descriptor for the open file
63+ ///
64+ /// The corresponding C function is `open`.
65+ @_alwaysEmitIntoClient
66+ public static func open(
67+ _ path: UnsafePointer < CChar > ,
68+ _ mode: FileDescriptor . AccessMode ,
69+ options: FileDescriptor . OpenOptions = FileDescriptor . OpenOptions ( ) ,
70+ permissions: FilePermissions ? = nil ,
71+ retryOnInterrupt: Bool = true
72+ ) throws -> FileDescriptor {
73+ try FileDescriptor . _open (
74+ path, mode, options: options, permissions: permissions, retryOnInterrupt: retryOnInterrupt
75+ ) . get ( )
3876 }
3977
78+ @usableFromInline
79+ internal static func _open(
80+ _ path: UnsafePointer < CChar > ,
81+ _ mode: FileDescriptor . AccessMode ,
82+ options: FileDescriptor . OpenOptions ,
83+ permissions: FilePermissions ? ,
84+ retryOnInterrupt: Bool
85+ ) -> Result < FileDescriptor , Errno > {
86+ let oFlag = mode. rawValue | options. rawValue
87+ let descOrError : Result < CInt , Errno > = valueOrErrno ( retryOnInterrupt: retryOnInterrupt) {
88+ if let permissions = permissions {
89+ return system_open ( path, oFlag, permissions. rawValue)
90+ }
91+ precondition ( !options. contains ( . create) ,
92+ " Create must be given permissions " )
93+ return system_open ( path, oFlag)
94+ }
95+ return descOrError. map { FileDescriptor ( rawValue: $0) }
96+ }
97+ #else
4098 /// Opens or creates a file for reading or writing.
4199 ///
42100 /// - Parameters:
@@ -83,6 +141,7 @@ extension FileDescriptor {
83141 }
84142 return descOrError. map { FileDescriptor ( rawValue: $0) }
85143 }
144+ #endif
86145
87146 /// Deletes a file descriptor.
88147 ///
@@ -308,7 +367,10 @@ extension FileDescriptor {
308367 buffer,
309368 retryOnInterrupt: retryOnInterrupt)
310369 }
370+ }
311371
372+ /*System 0.0.2, @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)*/
373+ extension FileDescriptor {
312374 /// Duplicate this file descriptor and return the newly created copy.
313375 ///
314376 /// - Parameters:
@@ -385,7 +447,7 @@ extension FileDescriptor {
385447 public static func pipe( ) throws -> ( readEnd: FileDescriptor , writeEnd: FileDescriptor ) {
386448 try _pipe ( ) . get ( )
387449 }
388-
450+
389451 /*System 1.1.0, @available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)*/
390452 @usableFromInline
391453 internal static func _pipe( ) -> Result < ( readEnd: FileDescriptor , writeEnd: FileDescriptor ) , Errno > {
0 commit comments