20
20
@_exported import TSCclibc
21
21
22
22
#if os(Windows)
23
+ private extension String {
24
+ func withCStringW< Result> ( _ body: ( UnsafePointer < wchar_t > , Int ) throws -> Result ) rethrows -> Result {
25
+ return try withCString ( encodedAs: UTF16 . self) {
26
+ let capacity : Int = wcslen ( $0) + 1
27
+ return try $0. withMemoryRebound ( to: wchar_t. self, capacity: capacity) {
28
+ try body ( $0, capacity)
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ private extension UnsafeMutablePointer where Pointee == CChar {
35
+ func assign( from source: UnsafePointer < wchar_t > ) {
36
+ String ( decodingCString: source, as: UTF16 . self) . utf8CString. withUnsafeBytes {
37
+ assign ( from: $0. bindMemory ( to: CChar . self) . baseAddress!,
38
+ count: $0. count)
39
+ }
40
+ }
41
+ }
42
+
23
43
// char *realpath(const char *path, char *resolved_path);
24
44
public func realpath(
25
45
_ path: String ,
26
46
_ resolvedPath: UnsafeMutablePointer < CChar > ?
27
47
) -> UnsafeMutablePointer < CChar > ? {
28
- fatalError ( " realpath is unimplemented " )
48
+ let result : UnsafeMutablePointer < CChar >
49
+ if let resolvedPath = resolvedPath {
50
+ result = resolvedPath
51
+ } else {
52
+ result = UnsafeMutablePointer< CChar> . allocate( capacity: Int ( MAX_PATH) )
53
+ }
54
+ return String ( cString: result) . withCStringW { resultW, capacity in
55
+ return path. withCStringW { pathW, _ in
56
+ guard _wfullpath ( UnsafeMutablePointer ( mutating: resultW) , pathW, capacity) != nil else {
57
+ return nil
58
+ }
59
+ result. assign ( from: resultW)
60
+ return result
61
+ }
62
+ }
29
63
}
30
64
31
65
// char *mkdtemp(char *template);
32
66
public func mkdtemp(
33
67
_ template: UnsafeMutablePointer < CChar > ?
34
68
) -> UnsafeMutablePointer < CChar > ? {
35
- fatalError ( " mkdtemp is unimplemented " )
69
+ guard let template = template else { return nil }
70
+
71
+ func createDirectory( ) -> UnsafeMutablePointer < CChar > ? {
72
+ let path = String ( String ( cString: template) . dropLast ( 6 ) +
73
+ String( Int . random ( in: 1 ..< 1000000 ) ) )
74
+ return path. withCStringW { pathW, _ in
75
+ guard CreateDirectoryW ( pathW, nil ) else {
76
+ return nil
77
+ }
78
+ template. assign ( from: pathW)
79
+ return template
80
+ }
81
+ }
82
+
83
+ var result : UnsafeMutablePointer < CChar > ?
84
+ repeat {
85
+ result = createDirectory ( )
86
+ } while result == nil && Int32 ( GetLastError ( ) ) == ERROR_ALREADY_EXISTS
87
+
88
+ return result
36
89
}
37
90
38
91
// int mkstemps(char *template, int suffixlen);
@@ -41,23 +94,17 @@ public func mkstemps(
41
94
_ suffixlen: Int32
42
95
) -> Int32 {
43
96
guard let template = template else { return - EINVAL }
44
- return String ( cString: template) . withCString ( encodedAs: UTF16 . self) {
45
- let capacity : Int = wcslen ( $0) + 1
46
- return $0. withMemoryRebound ( to: wchar_t. self, capacity: capacity) {
47
- guard _wmktemp_s ( UnsafeMutablePointer ( mutating: $0) , capacity) == 0 else {
48
- return - EINVAL
49
- }
97
+ return String ( cString: template) . withCStringW { templateW, capacity in
98
+ guard _wmktemp_s ( UnsafeMutablePointer ( mutating: templateW) , capacity) == 0 else {
99
+ return - EINVAL
100
+ }
50
101
51
- var fd : Int32 = - 1
52
- _wsopen_s ( & fd, $0 , _O_RDWR | _O_CREAT | _O_BINARY | _O_NOINHERIT,
53
- _SH_DENYNO, _S_IREAD | _S_IWRITE)
102
+ var fd : Int32 = - 1
103
+ _wsopen_s ( & fd, templateW , _O_RDWR | _O_CREAT | _O_BINARY | _O_NOINHERIT,
104
+ _SH_DENYNO, _S_IREAD | _S_IWRITE)
54
105
55
- String ( decodingCString: $0, as: UTF16 . self) . utf8CString. withUnsafeBytes {
56
- template. assign ( from: $0. bindMemory ( to: CChar . self) . baseAddress!,
57
- count: $0. count)
58
- }
59
- return fd
60
- }
106
+ template. assign ( from: templateW)
107
+ return fd
61
108
}
62
109
}
63
110
#endif
0 commit comments