|
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);
|
39 | 92 | public func mkstemps(
|
40 | 93 | _ template: UnsafeMutablePointer<CChar>?,
|
41 | 94 | _ suffixlen: Int32
|
42 | 95 | ) -> Int32 {
|
43 |
| - 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 |
| - } |
50 |
| - |
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) |
54 |
| - |
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 |
| 96 | + guard let template = template else { return -EINVAL } |
| 97 | + return String(cString: template).withCStringW { templateW, capacity in |
| 98 | + guard _wmktemp_s(UnsafeMutablePointer(mutating: templateW), capacity) == 0 else { |
| 99 | + return -EINVAL |
| 100 | + } |
| 101 | + |
| 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) |
| 105 | + |
| 106 | + template.assign(from: templateW) |
| 107 | + return fd |
60 | 108 | }
|
61 |
| - } |
62 | 109 | }
|
63 | 110 | #endif
|
0 commit comments