@@ -102,21 +102,6 @@ private func walk(directory path: URL, _ body: (String, DWORD) throws -> Void) r
102
102
}
103
103
}
104
104
105
- internal func joinPath( prefix: String , suffix: String ) -> String {
106
- var pszPath : PWSTR ?
107
-
108
- guard !prefix. isEmpty else { return suffix }
109
- guard !suffix. isEmpty else { return prefix }
110
-
111
- _ = try ! FileManager . default. _fileSystemRepresentation ( withPath: prefix, andPath: suffix) {
112
- PathAllocCombine ( $0, $1, ULONG ( PATHCCH_ALLOW_LONG_PATHS . rawValue) , & pszPath)
113
- }
114
-
115
- let path : String = String ( decodingCString: pszPath!, as: UTF16 . self)
116
- LocalFree ( pszPath)
117
- return path
118
- }
119
-
120
105
extension FileManager {
121
106
internal func _mountedVolumeURLs( includingResourceValuesForKeys propertyKeys: [ URLResourceKey ] ? , options: VolumeEnumerationOptions = [ ] ) -> [ URL ] ? {
122
107
var urls : [ URL ] = [ ]
@@ -168,145 +153,11 @@ extension FileManager {
168
153
}
169
154
170
155
internal func _attributesOfFileSystemIncludingBlockSize( forPath path: String ) throws -> ( attributes: [ FileAttributeKey : Any ] , blockSize: UInt64 ? ) {
171
- return ( attributes: try _attributesOfFileSystem ( forPath: path) , blockSize: nil )
172
- }
173
-
174
- internal func _attributesOfFileSystem( forPath path: String ) throws -> [ FileAttributeKey : Any ] {
175
- var result : [ FileAttributeKey : Any ] = [ : ]
176
-
177
- try FileManager . default. _fileSystemRepresentation ( withPath: path) {
178
- let dwLength : DWORD = GetFullPathNameW ( $0, 0 , nil , nil )
179
- guard dwLength > 0 else {
180
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
181
- }
182
-
183
- var szVolumePath : [ WCHAR ] = Array < WCHAR > ( repeating: 0 , count: Int ( dwLength + 1 ) )
184
- guard GetVolumePathNameW ( $0, & szVolumePath, dwLength) else {
185
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
186
- }
187
-
188
- var liTotal : ULARGE_INTEGER = ULARGE_INTEGER ( )
189
- var liFree : ULARGE_INTEGER = ULARGE_INTEGER ( )
190
- guard GetDiskFreeSpaceExW ( & szVolumePath, nil , & liTotal, & liFree) else {
191
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
192
- }
193
-
194
- let hr : HRESULT = PathCchStripToRoot ( & szVolumePath, szVolumePath. count)
195
- guard hr == S_OK || hr == S_FALSE else {
196
- throw _NSErrorWithWindowsError ( DWORD ( hr & 0xffff ) , reading: true , paths: [ path] )
197
- }
198
-
199
- var volumeSerialNumber : DWORD = 0
200
- guard GetVolumeInformationW ( & szVolumePath, nil , 0 , & volumeSerialNumber, nil , nil , nil , 0 ) else {
201
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
202
- }
203
-
204
- result [ . systemSize] = NSNumber ( value: liTotal. QuadPart)
205
- result [ . systemFreeSize] = NSNumber ( value: liFree. QuadPart)
206
- result [ . systemNumber] = NSNumber ( value: volumeSerialNumber)
207
- // FIXME(compnerd): what about .systemNodes, .systemFreeNodes?
208
- }
209
- return result
210
- }
211
-
212
- internal func _destinationOfSymbolicLink( atPath path: String ) throws -> String {
213
- let faAttributes = try windowsFileAttributes ( atPath: path)
214
- guard faAttributes. dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT else {
215
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_BAD_ARGUMENTS) , reading: false )
216
- }
217
-
218
- let handle : HANDLE = try FileManager . default. _fileSystemRepresentation ( withPath: path) {
219
- CreateFileW ( $0, GENERIC_READ,
220
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
221
- nil , OPEN_EXISTING,
222
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
223
- nil )
224
- }
225
- if handle == INVALID_HANDLE_VALUE {
226
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true )
227
- }
228
- defer { CloseHandle ( handle) }
229
-
230
- // Since REPARSE_DATA_BUFFER ends with an arbitrarily long buffer, we
231
- // have to manually get the path buffer out of it since binding it to a
232
- // type will truncate the path buffer.
233
- //
234
- // 20 is the sum of the offsets of:
235
- // ULONG ReparseTag
236
- // USHORT ReparseDataLength
237
- // USHORT Reserved
238
- // USHORT SubstituteNameOffset
239
- // USHORT SubstituteNameLength
240
- // USHORT PrintNameOffset
241
- // USHORT PrintNameLength
242
- // ULONG Flags (Symlink only)
243
- let symLinkPathBufferOffset = 20 // 4 + 2 + 2 + 2 + 2 + 2 + 2 + 4
244
- let mountPointPathBufferOffset = 16 // 4 + 2 + 2 + 2 + 2 + 2 + 2
245
- let buff = UnsafeMutableRawBufferPointer . allocate ( byteCount: Int ( MAXIMUM_REPARSE_DATA_BUFFER_SIZE) ,
246
- alignment: 8 )
247
-
248
- guard let buffBase = buff. baseAddress else {
249
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_INVALID_DATA) , reading: false )
250
- }
251
-
252
- var bytesWritten : DWORD = 0
253
- guard DeviceIoControl ( handle, FSCTL_GET_REPARSE_POINT, nil , 0 ,
254
- buffBase, DWORD ( MAXIMUM_REPARSE_DATA_BUFFER_SIZE) ,
255
- & bytesWritten, nil ) else {
256
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true )
257
- }
258
-
259
- guard bytesWritten >= MemoryLayout< REPARSE_DATA_BUFFER> . size else {
260
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_INVALID_DATA) , reading: false )
261
- }
262
-
263
- let bound = buff. bindMemory ( to: REPARSE_DATA_BUFFER . self)
264
- guard let reparseDataBuffer = bound. first else {
265
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_INVALID_DATA) , reading: false )
266
- }
267
-
268
- guard reparseDataBuffer. ReparseTag == IO_REPARSE_TAG_SYMLINK
269
- || reparseDataBuffer. ReparseTag == IO_REPARSE_TAG_MOUNT_POINT else {
270
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_BAD_ARGUMENTS) , reading: false )
271
- }
272
-
273
- let pathBufferPtr : UnsafeMutableRawPointer
274
- let substituteNameBytes : Int
275
- let substituteNameOffset : Int
276
- switch reparseDataBuffer. ReparseTag {
277
- case IO_REPARSE_TAG_SYMLINK:
278
- pathBufferPtr = buffBase + symLinkPathBufferOffset
279
- substituteNameBytes = Int ( reparseDataBuffer. SymbolicLinkReparseBuffer. SubstituteNameLength)
280
- substituteNameOffset = Int ( reparseDataBuffer. SymbolicLinkReparseBuffer. SubstituteNameOffset)
281
- case IO_REPARSE_TAG_MOUNT_POINT:
282
- pathBufferPtr = buffBase + mountPointPathBufferOffset
283
- substituteNameBytes = Int ( reparseDataBuffer. MountPointReparseBuffer. SubstituteNameLength)
284
- substituteNameOffset = Int ( reparseDataBuffer. MountPointReparseBuffer. SubstituteNameOffset)
285
- default :
286
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_BAD_ARGUMENTS) , reading: false )
287
- }
288
-
289
- guard substituteNameBytes + substituteNameOffset <= bytesWritten else {
290
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_INVALID_DATA) , reading: false )
291
- }
292
-
293
- let substituteNameBuff = Data ( bytes: pathBufferPtr + substituteNameOffset, count: substituteNameBytes)
294
- guard var substitutePath = String ( data: substituteNameBuff, encoding: . utf16LittleEndian) else {
295
- throw _NSErrorWithWindowsError ( DWORD ( ERROR_INVALID_DATA) , reading: false )
296
- }
297
-
298
- // Canonicalize the NT Object Manager Path to the DOS style path
299
- // instead. Unfortunately, there is no nice API which can allow us to
300
- // do this in a guranteed way.
301
- let kObjectManagerPrefix = " \\ ?? \\ "
302
- if substitutePath. hasPrefix ( kObjectManagerPrefix) {
303
- substitutePath = String ( substitutePath. dropFirst ( kObjectManagerPrefix. count) )
304
- }
305
- return substitutePath
156
+ return ( attributes: try attributesOfFileSystem ( forPath: path) , blockSize: nil )
306
157
}
307
158
308
159
private func _realpath( _ path: String ) -> String {
309
- return ( try ? _destinationOfSymbolicLink ( atPath: path) ) ?? path
160
+ return ( try ? destinationOfSymbolicLink ( atPath: path) ) ?? path
310
161
}
311
162
312
163
internal func _recursiveDestinationOfSymbolicLink( atPath path: String ) throws -> String {
0 commit comments