Skip to content

Commit 60d2b8f

Browse files
committed
Fix operatingSystemVersionString and operatingSystemVersion for Linux
- For Linux, use /proc/version_signature for the operatingSystemVersionString. - Use uname on non Darwin platforms to get the version kernel version.
1 parent 4b34eb5 commit 60d2b8f

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

Foundation/ProcessInfo.swift

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,23 @@ open class ProcessInfo: NSObject {
7777
}
7878

7979
open var operatingSystemVersionString: String {
80-
return CFCopySystemVersionString()?._swiftObject ?? "Unknown"
80+
let fallback = "Unknown"
81+
#if os(Linux)
82+
let version = try? String(contentsOf: URL(fileURLWithPath: "/proc/version_signature", isDirectory: false), encoding: .utf8)
83+
return version ?? fallback
84+
#else
85+
return CFCopySystemVersionString()?._swiftObject ?? fallback
86+
#endif
8187
}
8288

8389
open var operatingSystemVersion: OperatingSystemVersion {
8490
// The following fallback values match Darwin Foundation
8591
let fallbackMajor = -1
8692
let fallbackMinor = 0
8793
let fallbackPatch = 0
88-
94+
let versionString: String
95+
96+
#if canImport(Darwin)
8997
guard let systemVersionDictionary = _CFCopySystemVersionDictionary() else {
9098
return OperatingSystemVersion(majorVersion: fallbackMajor, minorVersion: fallbackMinor, patchVersion: fallbackPatch)
9199
}
@@ -94,8 +102,19 @@ open class ProcessInfo: NSObject {
94102
guard let productVersion = unsafeBitCast(CFDictionaryGetValue(systemVersionDictionary, productVersionKey), to: NSString?.self) else {
95103
return OperatingSystemVersion(majorVersion: fallbackMajor, minorVersion: fallbackMinor, patchVersion: fallbackPatch)
96104
}
97-
98-
let versionComponents = productVersion._swiftObject.split(separator: ".").map(String.init).compactMap({ Int($0) })
105+
versionString = productVersion._swiftObject
106+
#else
107+
var utsNameBuffer = utsname()
108+
guard uname(&utsNameBuffer) == 0 else {
109+
return OperatingSystemVersion(majorVersion: fallbackMajor, minorVersion: fallbackMinor, patchVersion: fallbackPatch)
110+
}
111+
let release = withUnsafePointer(to: &utsNameBuffer.release.0) {
112+
return String(cString: $0)
113+
}
114+
let idx = release.firstIndex(of: "-") ?? release.endIndex
115+
versionString = String(release[..<idx])
116+
#endif
117+
let versionComponents = versionString.split(separator: ".").map(String.init).compactMap({ Int($0) })
99118
let majorVersion = versionComponents.dropFirst(0).first ?? fallbackMajor
100119
let minorVersion = versionComponents.dropFirst(1).first ?? fallbackMinor
101120
let patchVersion = versionComponents.dropFirst(2).first ?? fallbackPatch

TestFoundation/TestProcessInfo.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ class TestProcessInfo : XCTestCase {
2525

2626
let version = processInfo.operatingSystemVersion
2727
XCTAssert(version.majorVersion != 0)
28+
29+
#if os(Linux) || canImport(Darwin)
30+
let minVersion = OperatingSystemVersion(majorVersion: 1, minorVersion: 0, patchVersion: 0)
31+
XCTAssertTrue(processInfo.isOperatingSystemAtLeast(minVersion))
32+
#endif
2833
}
2934

3035
func test_processName() {

0 commit comments

Comments
 (0)