//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//
internal import _FoundationCShims
#if canImport(Darwin)
import Darwin
internal import MachO.dyld
fileprivate let _pageSize: Int = {
Int(_platform_shims_vm_size())
}()
#elseif canImport(WinSDK)
import WinSDK
fileprivate let _pageSize: Int = {
var sysInfo: SYSTEM_INFO = SYSTEM_INFO()
GetSystemInfo(&sysInfo)
return Int(sysInfo.dwPageSize)
}()
#elseif os(WASI)
// WebAssembly defines a fixed page size
fileprivate let _pageSize: Int = 65_536
#elseif canImport(Android)
@preconcurrency import Android
fileprivate let _pageSize: Int = Int(getpagesize())
#elseif canImport(Glibc)
@preconcurrency import Glibc
fileprivate let _pageSize: Int = Int(getpagesize())
#elseif canImport(Musl)
@preconcurrency import Musl
fileprivate let _pageSize: Int = Int(getpagesize())
#elseif canImport(C)
fileprivate let _pageSize: Int = Int(getpagesize())
#endif // canImport(Darwin)
#if FOUNDATION_FRAMEWORK
internal import CoreFoundation_Private
#endif
package struct Platform {
static var pageSize: Int {
_pageSize
}
static let MAX_HOSTNAME_LENGTH = 1024
static func roundDownToMultipleOfPageSize(_ size: Int) -> Int {
return size & ~(self.pageSize - 1)
}
static func roundUpToMultipleOfPageSize(_ size: Int) -> Int {
return (self.pageSize + size - 1) & ~(self.pageSize - 1)
}
static func copyMemoryPages(_ source: UnsafeRawPointer, _ dest: UnsafeMutableRawPointer, _ length: Int) {
#if canImport(Darwin)
if vm_copy(
_platform_mach_task_self(),
vm_address_t(UInt(bitPattern: source)),
vm_size_t(length),
vm_address_t(UInt(bitPattern: dest))) != KERN_SUCCESS {
memmove(dest, source, length)
}
#else
memmove(dest, source, length)
#endif // canImport(Darwin)
}
}
// MARK: - EUID & EGID
#if !NO_PROCESS
#if canImport(Darwin)
private func _getSVUID() -> uid_t? {
var kinfo = kinfo_proc()
var len: size_t = 0
var mib = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
let ret = mib.withUnsafeMutableBufferPointer {
sysctl($0.baseAddress!, u_int($0.count), &kinfo, &len, nil, 0)
}
guard ret == 0 else { return nil }
return kinfo.kp_eproc.e_pcred.p_svuid
}
private let _canChangeUIDs: Bool = {
let euid = geteuid()
let uid = getuid()
let svuid = _getSVUID()
return uid == 0 || uid != euid || svuid != euid || svuid == nil
}()
private func _lookupUGIDs() -> (uid_t, gid_t) {
var uRes = uid_t()
var gRes = gid_t()
if pthread_getugid_np(&uRes, &gRes) != 0 {
uRes = geteuid()
gRes = getegid()
}
return (uRes, gRes)
}
private let _cachedUGIDs: (uid_t, gid_t) = {
_lookupUGIDs()
}()
#endif
#if !os(Windows) && !os(WASI)
extension Platform {
private static var ROOT_USER: UInt32 { 0 }
static func getUGIDs(allowEffectiveRootUID: Bool = true) -> (uid: UInt32, gid: UInt32) {
var result: (uid: UInt32, gid: UInt32)
#if canImport(Darwin)
if _canChangeUIDs {
result = _lookupUGIDs()
} else {
result = _cachedUGIDs
}
#else
result = (uid: geteuid(), gid: getegid())
#endif
// Some callers need to use the real UID in cases where a process has called seteuid(0)
// If that is the case for this caller, and the eUID is the root user, return the real UID instead
if !allowEffectiveRootUID && result.uid == Self.ROOT_USER {
result.uid = getuid()
}
return result
}
#if canImport(Darwin)
typealias Operation = (Input, UnsafeMutablePointer