@@ -264,8 +264,14 @@ extension FileManager {
264
264
}
265
265
266
266
internal func _createSymbolicLink( atPath path: String , withDestinationPath destPath: String ) throws {
267
- let faAttributes : WIN32_FILE_ATTRIBUTE_DATA = try windowsFileAttributes ( atPath: path)
268
- var dwFlags : DWORD = DWORD ( SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
267
+ var dwFlags = DWORD ( SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
268
+ // Note: windowsfileAttributes will throw if the destPath is not found.
269
+ // Since on Windows, you are required to know the type of the symlink
270
+ // target (file or directory) during creation, and assuming one or the
271
+ // other doesn't make a lot of sense, we allow it to throw, thus
272
+ // disallowing the creation of broken symlinks on Windows (unlike with
273
+ // POSIX).
274
+ let faAttributes = try windowsFileAttributes ( atPath: destPath)
269
275
if faAttributes. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) == DWORD ( FILE_ATTRIBUTE_DIRECTORY) {
270
276
dwFlags |= DWORD ( SYMBOLIC_LINK_FLAG_DIRECTORY)
271
277
}
@@ -286,12 +292,16 @@ extension FileManager {
286
292
internal func _canonicalizedPath( toFileAtPath path: String ) throws -> String {
287
293
var hFile : HANDLE = INVALID_HANDLE_VALUE
288
294
path. withCString ( encodedAs: UTF16 . self) { link in
289
- hFile = CreateFileW ( link, GENERIC_READ, DWORD ( FILE_SHARE_WRITE) , nil , DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_BACKUP_SEMANTICS) , nil )
295
+ // BACKUP_SEMANTICS are (confusingly) required in order to receive a
296
+ // handle to a directory
297
+ hFile = CreateFileW ( link, 0 , DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
298
+ nil , DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_BACKUP_SEMANTICS) ,
299
+ nil )
290
300
}
291
- defer { CloseHandle ( hFile) }
292
301
if hFile == INVALID_HANDLE_VALUE {
293
302
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true )
294
303
}
304
+ defer { CloseHandle ( hFile) }
295
305
296
306
let dwLength : DWORD = GetFinalPathNameByHandleW ( hFile, nil , 0 , DWORD ( FILE_NAME_NORMALIZED) )
297
307
var szPath : [ WCHAR ] = Array < WCHAR > ( repeating: 0 , count: Int ( dwLength + 1 ) )
0 commit comments