Skip to content

Commit ab1e889

Browse files
committed
Simplify a few API calls in FSProxy
These now go through Foundation rather than Win32 APIs directly. This simplifies Unicode and long path handling in particular. For realpath I left the POSIX implementation in place for non-Windows for now since it's not clear that has equivalent behavior. touch/setFileTimestamp now differ in that they no longer set atime, but virtually nothing uses atime.
1 parent 19cdeaa commit ab1e889

File tree

1 file changed

+6
-81
lines changed

1 file changed

+6
-81
lines changed

Sources/SWBUtil/FSProxy.swift

+6-81
Original file line numberDiff line numberDiff line change
@@ -615,69 +615,15 @@ class LocalFS: FSProxy, @unchecked Sendable {
615615
}
616616

617617
func touch(_ path: Path) throws {
618-
#if os(Windows)
619-
let handle: HANDLE = path.withPlatformString {
620-
CreateFileW($0, DWORD(GENERIC_WRITE), DWORD(FILE_SHARE_READ), nil,
621-
DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil)
622-
}
623-
if handle == INVALID_HANDLE_VALUE {
624-
throw Win32Error(GetLastError())
625-
}
626-
try handle.closeAfter {
627-
var ft = FILETIME()
628-
var st = SYSTEMTIME()
629-
GetSystemTime(&st)
630-
SystemTimeToFileTime(&st, &ft)
631-
if !SetFileTime(handle, nil, &ft, &ft) {
632-
Win32Error(GetLastError())
633-
}
634-
}
635-
#else
636-
try eintrLoop {
637-
guard utimensat(AT_FDCWD, path.str, nil, 0) == 0 else {
638-
throw POSIXError(errno, context: "utimensat", "AT_FDCWD", path.str)
639-
}
640-
}
641-
#endif
618+
try _setFileTimestamp(path, timestamp: Date())
642619
}
643620

644621
func setFileTimestamp(_ path: Path, timestamp: Int) throws {
645-
#if os(Windows)
646-
let handle: HANDLE = path.withPlatformString {
647-
CreateFileW($0, DWORD(GENERIC_WRITE), DWORD(FILE_SHARE_READ), nil,
648-
DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil)
649-
}
650-
if handle == INVALID_HANDLE_VALUE {
651-
throw Win32Error(GetLastError())
652-
}
653-
try handle.closeAfter {
654-
// Number of 100ns intervals between 1601 and 1970 epochs
655-
let delta = 116444736000000000
656-
657-
let ll = UInt64((timestamp * 10000000) + delta)
658-
659-
var timeInt = ULARGE_INTEGER()
660-
timeInt.QuadPart = ll
622+
try _setFileTimestamp(path, timestamp: Date(timeIntervalSince1970: Double(timestamp)))
623+
}
661624

662-
var ft = FILETIME()
663-
ft.dwLowDateTime = timeInt.LowPart
664-
ft.dwHighDateTime = timeInt.HighPart
665-
if !SetFileTime(handle, nil, &ft, &ft) {
666-
throw Win32Error(GetLastError())
667-
}
668-
}
669-
#else
670-
try eintrLoop {
671-
#if os(Linux) || os(Android)
672-
let UTIME_OMIT = 1073741822
673-
#endif
674-
let atime = timespec(tv_sec: 0, tv_nsec: Int(UTIME_OMIT))
675-
let mtime = timespec(tv_sec: time_t(timestamp), tv_nsec: 0)
676-
guard utimensat(AT_FDCWD, path.str, [atime, mtime], 0) == 0 else {
677-
throw POSIXError(errno, context: "utimensat", "AT_FDCWD", path.str, String(timestamp))
678-
}
679-
}
680-
#endif
625+
private func _setFileTimestamp(_ path: Path, timestamp: Date) throws {
626+
try fileManager.setAttributes([.modificationDate: timestamp], ofItemAtPath: path.str)
681627
}
682628

683629
func getFileInfo(_ path: Path) throws -> FileInfo {
@@ -875,28 +821,7 @@ class LocalFS: FSProxy, @unchecked Sendable {
875821

876822
func realpath(_ path: Path) throws -> Path {
877823
#if os(Windows)
878-
let handle: HANDLE = path.withPlatformString {
879-
CreateFileW($0, GENERIC_READ, DWORD(FILE_SHARE_READ), nil,
880-
DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil)
881-
}
882-
if handle == INVALID_HANDLE_VALUE {
883-
throw POSIXError(ENOENT, context: "realpath", path.str)
884-
}
885-
return try handle.closeAfter {
886-
let dwLength: DWORD = GetFinalPathNameByHandleW(handle, nil, 0, DWORD(FILE_NAME_NORMALIZED))
887-
return try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) {
888-
guard GetFinalPathNameByHandleW(handle, $0.baseAddress!, DWORD($0.count),
889-
DWORD(FILE_NAME_NORMALIZED)) == dwLength - 1 else {
890-
throw Win32Error(GetLastError())
891-
}
892-
let path = String(platformString: $0.baseAddress!)
893-
// Drop UNC prefix if present
894-
if path.hasPrefix(#"\\?\"#) {
895-
return Path(path.dropFirst(4))
896-
}
897-
return Path(path)
898-
}
899-
}
824+
return Path(path.str.resolvingSymlinksInPath)
900825
#else
901826
guard let result = SWBLibc.realpath(path.str, nil) else { throw POSIXError(errno, context: "realpath", path.str) }
902827
defer { free(result) }

0 commit comments

Comments
 (0)