Skip to content

Commit c10f658

Browse files
committed
[Windows] Modify What Counts as a Regular File
- Reparse points should be checked to ensure they are actually symlinks - A regular file may not have FILE_ATTRIBUTE_REGULAR set. It may have alternative attributes like FILE_ATTRIBUTE_ARCHIVE or FILE_ATTRIUBTE_HIDDDEN and should still count as a regular file.
1 parent 95fcab2 commit c10f658

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

Foundation/FileManager+Win32.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ extension FileManager {
329329
var faAttributes: WIN32_FILE_ATTRIBUTE_DATA = WIN32_FILE_ATTRIBUTE_DATA()
330330
do { faAttributes = try windowsFileAttributes(atPath: srcPath) } catch { return }
331331

332-
var fileType = FileAttributeType(attributes: faAttributes)
332+
var fileType = FileAttributeType(attributes: faAttributes, atPath: srcPath)
333333
if fileType == .typeDirectory {
334334
try createDirectory(atPath: dstPath, withIntermediateDirectories: false, attributes: nil)
335335
guard let enumerator = enumerator(atPath: srcPath) else {
@@ -341,7 +341,7 @@ extension FileManager {
341341
let dst = joinPath(prefix: dstPath, suffix: item)
342342

343343
do { faAttributes = try windowsFileAttributes(atPath: src) } catch { return }
344-
fileType = FileAttributeType(attributes: faAttributes)
344+
fileType = FileAttributeType(attributes: faAttributes, atPath: srcPath)
345345
if fileType == .typeDirectory {
346346
try createDirectory(atPath: dst, withIntermediateDirectories: false, attributes: nil)
347347
} else {

Foundation/FileManager.swift

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ open class FileManager : NSObject {
361361

362362
#if os(Windows)
363363
result[.deviceIdentifier] = NSNumber(value: UInt64(s.st_rdev))
364-
let type = FileAttributeType(attributes: try windowsFileAttributes(atPath: path))
364+
let type = FileAttributeType(attributes: try windowsFileAttributes(atPath: path), atPath: path)
365365
#else
366366
if let pwd = getpwuid(s.st_uid), pwd.pointee.pw_name != nil {
367367
let name = String(cString: pwd.pointee.pw_name)
@@ -937,18 +937,33 @@ public struct FileAttributeType : RawRepresentable, Equatable, Hashable {
937937
}
938938

939939
#if os(Windows)
940-
internal init(attributes: WIN32_FILE_ATTRIBUTE_DATA) {
940+
internal init(attributes: WIN32_FILE_ATTRIBUTE_DATA, atPath path: String) {
941941
if attributes.dwFileAttributes & DWORD(FILE_ATTRIBUTE_DIRECTORY) == DWORD(FILE_ATTRIBUTE_DIRECTORY) {
942942
self = .typeDirectory
943943
} else if attributes.dwFileAttributes & DWORD(FILE_ATTRIBUTE_DEVICE) == DWORD(FILE_ATTRIBUTE_DEVICE) {
944944
self = .typeCharacterSpecial
945945
} else if attributes.dwFileAttributes & DWORD(FILE_ATTRIBUTE_REPARSE_POINT) == DWORD(FILE_ATTRIBUTE_REPARSE_POINT) {
946-
// FIXME(compnerd) this is a lie! It may be a junction or a hard link
947-
self = .typeSymbolicLink
948-
} else if attributes.dwFileAttributes & DWORD(FILE_ATTRIBUTE_NORMAL) == DWORD(FILE_ATTRIBUTE_NORMAL) {
949-
self = .typeRegular
946+
// A reparse point may or may not actually be a symbolic link, we need to read the reparse tag
947+
let fileHandle = path.withCString(encodedAs: UTF16.self) {
948+
CreateFileW(/*lpFileName=*/$0,
949+
/*dwDesiredAccess=*/DWORD(0),
950+
/*dwShareMode=*/DWORD(FILE_SHARE_READ | FILE_SHARE_WRITE),
951+
/*lpSecurityAttributes=*/nil,
952+
/*dwCreationDisposition=*/DWORD(OPEN_EXISTING),
953+
/*dwFlagsAndAttributes=*/DWORD(FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS),
954+
/*hTemplateFile=*/nil)
955+
}
956+
var tagInfo = FILE_ATTRIBUTE_TAG_INFO()
957+
guard 0 != GetFileInformationByHandleEx(fileHandle,
958+
FileAttributeTagInfo,
959+
&tagInfo,
960+
DWORD(MemoryLayout<FILE_ATTRIBUTE_TAG_INFO>.size)) else {
961+
self = .typeUnknown
962+
return
963+
}
964+
self = tagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK ? .typeSymbolicLink : .typeRegular
950965
} else {
951-
self = .typeUnknown
966+
self = .typeRegular
952967
}
953968
}
954969
#else

0 commit comments

Comments
 (0)