From 147b692cf5f220552ce6af2470ab45b7c44e1ea8 Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Mon, 7 Apr 2025 13:46:18 -0400 Subject: [PATCH] OpenBSD support. (#1126) * Advise porter on where to make necessary change. In #1075 the change was already made for BSD (thank you!); my working edit had this guidance to ensure future porters get an error directing them where to make a necessary change. Otherwise, the FoundationEssentials build will fail and complain these variables are not defined but not have guidance as to where they are sourced from. * OpenBSD does not support extended attributes. * OpenBSD does not have secure_getenv. * Remaining OpenBSD changes. * OpenBSD also needs `pthread_mutex_t?`. * Originally I followed Darwin's check with `d_namlen`, but this should work too. * Correct statvfs type casts for OpenBSD. On OpenBSD, fsblkcnt_t -- the type of f_blocks -- is a UInt64; therefore, so must `blockSize` be. Ultimately, both sides of the `totalSizeBytes` multiplication should probably be type cast for all platforms, but that's a more significant functional change for another time. * Default activeProcessorCount to 1, not 0. After a rather tedious debugging session trying to figure out why swiftpm-bootstrap appeared to be deadlocked, this turned out to be the culprit. Perhaps this should be #error instead, but for now, set a sensible default. * Use sysconf for activeProcessorCount. This is what Dispatch does in some places for OpenBSD anyway, so do likewise here. --- Sources/FoundationEssentials/Data/Data+Reading.swift | 2 ++ Sources/FoundationEssentials/Data/Data+Writing.swift | 2 ++ .../FileManager/FileManager+Directories.swift | 2 +- .../FileManager/FileManager+Files.swift | 9 ++++++--- .../FileManager/FileManager+Utilities.swift | 2 +- .../FileManager/FileOperations+Enumeration.swift | 4 +++- .../FileManager/FileOperations.swift | 4 ++-- Sources/FoundationEssentials/LockedState.swift | 2 +- Sources/FoundationEssentials/Platform.swift | 2 +- .../FoundationEssentials/ProcessInfo/ProcessInfo.swift | 4 ++-- Sources/_FoundationCShims/include/_CStdlib.h | 4 ++++ 11 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Sources/FoundationEssentials/Data/Data+Reading.swift b/Sources/FoundationEssentials/Data/Data+Reading.swift index 37efea90f..01ce0739c 100644 --- a/Sources/FoundationEssentials/Data/Data+Reading.swift +++ b/Sources/FoundationEssentials/Data/Data+Reading.swift @@ -40,6 +40,8 @@ func _fgetxattr(_ fd: Int32, _ name: UnsafePointer!, _ value: UnsafeMutab return fgetxattr(fd, name, value, size, position, options) #elseif os(FreeBSD) return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size) +#elseif os(OpenBSD) + return -1 #elseif canImport(Glibc) || canImport(Musl) || canImport(Android) return fgetxattr(fd, name, value, size) #else diff --git a/Sources/FoundationEssentials/Data/Data+Writing.swift b/Sources/FoundationEssentials/Data/Data+Writing.swift index 657f2ae2e..af49745d6 100644 --- a/Sources/FoundationEssentials/Data/Data+Writing.swift +++ b/Sources/FoundationEssentials/Data/Data+Writing.swift @@ -639,6 +639,8 @@ private func writeExtendedAttributes(fd: Int32, attributes: [String : Data]) { _ = fsetxattr(fd, key, valueBuf.baseAddress!, valueBuf.count, 0, 0) #elseif os(FreeBSD) _ = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, key, valueBuf.baseAddress!, valueBuf.count) +#elseif os(OpenBSD) + return #elseif canImport(Glibc) || canImport(Musl) _ = fsetxattr(fd, key, valueBuf.baseAddress!, valueBuf.count, 0) #endif diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Directories.swift b/Sources/FoundationEssentials/FileManager/FileManager+Directories.swift index 41bb83eb0..4371f24ad 100644 --- a/Sources/FoundationEssentials/FileManager/FileManager+Directories.swift +++ b/Sources/FoundationEssentials/FileManager/FileManager+Directories.swift @@ -201,7 +201,7 @@ extension _FileManagerImpl { } } return results -#elseif os(WASI) +#elseif os(WASI) || os(OpenBSD) // wasi-libc does not support FTS for now throw CocoaError.errorWithFilePath(.featureUnsupported, path) #else diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift index 8f0083f04..118712a64 100644 --- a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift +++ b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift @@ -485,7 +485,7 @@ extension _FileManagerImpl { #endif } -#if !os(Windows) && !os(WASI) +#if !os(Windows) && !os(WASI) && !os(OpenBSD) private func _extendedAttribute(_ key: UnsafePointer, at path: UnsafePointer, followSymlinks: Bool) throws -> Data? { #if canImport(Darwin) var size = getxattr(path, key, nil, 0, 0, followSymlinks ? 0 : XATTR_NOFOLLOW) @@ -647,7 +647,7 @@ extension _FileManagerImpl { var attributes = statAtPath.fileAttributes try? Self._catInfo(for: URL(filePath: path, directoryHint: .isDirectory), statInfo: statAtPath, into: &attributes) - #if !os(WASI) // WASI does not support extended attributes + #if !os(WASI) && !os(OpenBSD) if let extendedAttrs = try? _extendedAttributes(at: fsRep, followSymlinks: false) { attributes[._extendedAttributes] = extendedAttrs } @@ -736,6 +736,9 @@ extension _FileManagerImpl { #if canImport(Darwin) let fsNumber = result.f_fsid.val.0 let blockSize = UInt64(result.f_bsize) + #elseif os(OpenBSD) + let fsNumber = result.f_fsid + let blockSize = UInt64(result.f_bsize) #else let fsNumber = result.f_fsid let blockSize = UInt(result.f_frsize) @@ -950,7 +953,7 @@ extension _FileManagerImpl { try Self._setCatInfoAttributes(attributes, path: path) if let extendedAttrs = attributes[.init("NSFileExtendedAttributes")] as? [String : Data] { - #if os(WASI) + #if os(WASI) || os(OpenBSD) // WASI does not support extended attributes throw CocoaError.errorWithFilePath(.featureUnsupported, path) #elseif canImport(Android) diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift b/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift index d2e54be75..d882a67bb 100644 --- a/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift +++ b/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift @@ -178,7 +178,7 @@ extension _FileManagerImpl { #endif } -#if !os(Windows) && !os(WASI) +#if !os(Windows) && !os(WASI) && !os(OpenBSD) static func _setAttribute(_ key: UnsafePointer, value: Data, at path: UnsafePointer, followSymLinks: Bool) throws { try value.withUnsafeBytes { buffer in #if canImport(Darwin) diff --git a/Sources/FoundationEssentials/FileManager/FileOperations+Enumeration.swift b/Sources/FoundationEssentials/FileManager/FileOperations+Enumeration.swift index dc9eff2eb..1d497f8c4 100644 --- a/Sources/FoundationEssentials/FileManager/FileOperations+Enumeration.swift +++ b/Sources/FoundationEssentials/FileManager/FileOperations+Enumeration.swift @@ -354,7 +354,8 @@ struct _POSIXDirectoryContentsSequence: Sequence { continue } #endif - #if os(FreeBSD) + + #if os(FreeBSD) || os(OpenBSD) guard dent.pointee.d_fileno != 0 else { continue } @@ -363,6 +364,7 @@ struct _POSIXDirectoryContentsSequence: Sequence { continue } #endif + // Use name let fileName: String #if os(WASI) diff --git a/Sources/FoundationEssentials/FileManager/FileOperations.swift b/Sources/FoundationEssentials/FileManager/FileOperations.swift index 93c98fc74..3d9a769f4 100644 --- a/Sources/FoundationEssentials/FileManager/FileOperations.swift +++ b/Sources/FoundationEssentials/FileManager/FileOperations.swift @@ -921,7 +921,7 @@ enum _FileOperations { } var current: off_t = 0 - #if os(WASI) + #if os(WASI) || os(OpenBSD) // WASI doesn't have sendfile, so we need to do it in user space with read/write try withUnsafeTemporaryAllocation(of: UInt8.self, capacity: chunkSize) { buffer in while current < total { @@ -958,7 +958,7 @@ enum _FileOperations { #if !canImport(Darwin) private static func _copyDirectoryMetadata(srcFD: CInt, srcPath: @autoclosure () -> String, dstFD: CInt, dstPath: @autoclosure () -> String, delegate: some LinkOrCopyDelegate) throws { - #if !os(WASI) && !os(Android) + #if !os(WASI) && !os(Android) && !os(OpenBSD) // Copy extended attributes #if os(FreeBSD) // FreeBSD uses the `extattr_*` calls for setting extended attributes. Unlike like, the namespace for the extattrs are not determined by prefix of the attribute diff --git a/Sources/FoundationEssentials/LockedState.swift b/Sources/FoundationEssentials/LockedState.swift index cf9d89b8f..2316fb955 100644 --- a/Sources/FoundationEssentials/LockedState.swift +++ b/Sources/FoundationEssentials/LockedState.swift @@ -31,7 +31,7 @@ package struct LockedState { private struct _Lock { #if canImport(os) typealias Primitive = os_unfair_lock -#elseif os(FreeBSD) +#elseif os(FreeBSD) || os(OpenBSD) typealias Primitive = pthread_mutex_t? #elseif canImport(Bionic) || canImport(Glibc) || canImport(Musl) typealias Primitive = pthread_mutex_t diff --git a/Sources/FoundationEssentials/Platform.swift b/Sources/FoundationEssentials/Platform.swift index 5177da6ca..1e39051b8 100644 --- a/Sources/FoundationEssentials/Platform.swift +++ b/Sources/FoundationEssentials/Platform.swift @@ -224,7 +224,7 @@ extension Platform { // MARK: - Environment Variables extension Platform { static func getEnvSecure(_ name: String) -> String? { - #if canImport(Glibc) + #if canImport(Glibc) && !os(OpenBSD) if let value = secure_getenv(name) { return String(cString: value) } else { diff --git a/Sources/FoundationEssentials/ProcessInfo/ProcessInfo.swift b/Sources/FoundationEssentials/ProcessInfo/ProcessInfo.swift index 6db2b3c9d..1caa04bfb 100644 --- a/Sources/FoundationEssentials/ProcessInfo/ProcessInfo.swift +++ b/Sources/FoundationEssentials/ProcessInfo/ProcessInfo.swift @@ -469,7 +469,7 @@ extension _ProcessInfo { return 0 } return Int(count) -#elseif os(Linux) || os(FreeBSD) || canImport(Android) +#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || canImport(Android) #if os(Linux) if let fsCount = Self.fsCoreCount() { return fsCount @@ -481,7 +481,7 @@ extension _ProcessInfo { GetSystemInfo(&sysInfo) return sysInfo.dwActiveProcessorMask.nonzeroBitCount #else - return 0 + return 1 #endif } diff --git a/Sources/_FoundationCShims/include/_CStdlib.h b/Sources/_FoundationCShims/include/_CStdlib.h index 6aba41be3..405febca9 100644 --- a/Sources/_FoundationCShims/include/_CStdlib.h +++ b/Sources/_FoundationCShims/include/_CStdlib.h @@ -156,6 +156,10 @@ #ifndef TZDEFAULT #define TZDEFAULT "/etc/localtime" #endif /* !defined TZDEFAULT */ +#elif TARGET_OS_WINDOWS +/* not required */ +#else +#error "possibly define TZDIR and TZDEFAULT for this platform" #endif /* TARGET_OS_MAC || TARGET_OS_LINUX || TARGET_OS_BSD */ #endif