URL.resourceValues(forKeys: [.fileSizeKey]) value too large

Swift version 6.2.3
Windows 25H2 ARM (parallels, VM)

let resourceValues = try filePathURL.resourceValues(forKeys: [.fileSizeKey])
For a local file larger than 4GB throws

Error Domain=NSCocoaErrorDomain Code=256 "(null)"UserInfo={NSFilePath=C:/Users/kdeda/Developer/testBZDone.log, NSUnderlyingError=Error Domain=NSPOSIXErrorDomain Code=132 "value too large"}

The following works

let attributes = try FileManager.default.attributesOfItem(atPath: filePathURL.path)
if let fileSize = attributes[FileAttributeKey.size] as? NSNumber {
    return fileSize.int64Value
}

On the latest swift-corelibs-foundation I see a potential reason

internal func _statxFile(atPath path: String, withFileSystemRepresentation fsRep: UnsafePointer<NativeFSRCharType>? = nil) throws -> (stat, UInt64) {
...
        guard info.nFileSizeHigh == 0 else {
            throw _NSErrorWithErrno(EOVERFLOW, reading: true, path: path)
        }

@compnerd Could you shed some light into this ?

and then:

        statInfo.st_size = _off_t(info.nFileSizeLow)

The fix could be:

        statInfo.st_size = _off_t(info.nFileSizeHigh) << 32 | _off_t(info.nFileSizeLow)

along with removing the above overflow check.

IIRC, the reason that the >4G raises an overflow error is because the _statxFile is an internal function that has full visibility but the public interface which uses it returns a 32-bit value. As a result, we would silently truncate the value. If the interface has since changed and now returns a 64-bit value, we should be able to re-constitute the 64-bit value and return that as we would have the full range available.

It ultimately uses the Win32 _stat type, which uses 32-bit integers as you say. There's an alternative _wstat64 structure and corresponding function we could migrate to that would use 64-bit integers as well as WCHAR strings (if we need them.) Shouldn't be too much work, mostly rote translation.

Hmm, I do remember looking at the 8 different stat variants. I know that they have the 64-bit variants, but ISTR that I hadn't used that because the truncation was happening at the Foundation/CoreFoundation layer, not the Win32. Note that I was explicitly checking the high bits on the existing stat and rather than re-composing the value, raising an error.