From 4db3c7a536ff33d66221e6acd77ccbad631abe2a Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 26 Jul 2024 07:19:58 +0000 Subject: [PATCH 1/2] Guard out user/group related code on WASI This change guards out the user/group related code on WASI, as WASI does not have the concept of users or groups. --- Sources/FoundationEssentials/Data/Data+Writing.swift | 2 ++ .../FoundationEssentials/FileManager/FileManager+Files.swift | 2 ++ .../FileManager/FileManager+Utilities.swift | 2 +- Sources/FoundationEssentials/FileManager/FileOperations.swift | 2 ++ Sources/FoundationEssentials/Platform.swift | 4 ++-- Sources/FoundationEssentials/String/String+Path.swift | 2 ++ 6 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Sources/FoundationEssentials/Data/Data+Writing.swift b/Sources/FoundationEssentials/Data/Data+Writing.swift index 4f92cb1a6..ffd8078e8 100644 --- a/Sources/FoundationEssentials/Data/Data+Writing.swift +++ b/Sources/FoundationEssentials/Data/Data+Writing.swift @@ -514,6 +514,7 @@ private func writeToFileAux(path inPath: PathOrURL, buffer: UnsafeRawBufferPoint cleanupTemporaryDirectory(at: temporaryDirectoryPath) +#if !os(WASI) // WASI does not support fchmod for now if let mode { // Try to change the mode if the path has not changed. Do our best, but don't report an error. #if FOUNDATION_FRAMEWORK @@ -537,6 +538,7 @@ private func writeToFileAux(path inPath: PathOrURL, buffer: UnsafeRawBufferPoint fchmod(fd, mode) #endif } +#endif // os(WASI) } } } diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift index 9bb8f0bbb..cbe4f452d 100644 --- a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift +++ b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift @@ -905,6 +905,7 @@ extension _FileManagerImpl { let group = attributes[.groupOwnerAccountName] as? String let groupID = _readFileAttributePrimitive(attributes[.groupOwnerAccountID], as: UInt.self) + #if !os(WASI) // WASI does not have the concept of users or groups if user != nil || userID != nil || group != nil || groupID != nil { // Bias toward userID & groupID - try to prevent round trips to getpwnam if possible. var leaveUnchanged: UInt32 { UInt32(bitPattern: -1) } @@ -914,6 +915,7 @@ extension _FileManagerImpl { throw CocoaError.errorWithFilePath(path, errno: errno, reading: false) } } + #endif try Self._setCatInfoAttributes(attributes, path: path) diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift b/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift index 624b1125f..3d01a2e44 100644 --- a/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift +++ b/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift @@ -267,7 +267,7 @@ extension _FileManagerImpl { } #endif -#if !os(Windows) +#if !os(Windows) && !os(WASI) static func _userAccountNameToNumber(_ name: String) -> uid_t? { name.withCString { ptr in getpwnam(ptr)?.pointee.pw_uid diff --git a/Sources/FoundationEssentials/FileManager/FileOperations.swift b/Sources/FoundationEssentials/FileManager/FileOperations.swift index 8e67a771f..130a07ba4 100644 --- a/Sources/FoundationEssentials/FileManager/FileOperations.swift +++ b/Sources/FoundationEssentials/FileManager/FileOperations.swift @@ -855,12 +855,14 @@ enum _FileOperations { } defer { close(dstfd) } + #if !os(WASI) // WASI doesn't have fchmod for now // Set the file permissions using fchmod() instead of when open()ing to avoid umask() issues let permissions = fileInfo.st_mode & ~S_IFMT guard fchmod(dstfd, permissions) == 0 else { try delegate.throwIfNecessary(errno, String(cString: srcPtr), String(cString: dstPtr)) return } + #endif if fileInfo.st_size == 0 { // no copying required diff --git a/Sources/FoundationEssentials/Platform.swift b/Sources/FoundationEssentials/Platform.swift index 20dc561af..bf2e652d3 100644 --- a/Sources/FoundationEssentials/Platform.swift +++ b/Sources/FoundationEssentials/Platform.swift @@ -113,7 +113,7 @@ private let _cachedUGIDs: (uid_t, gid_t) = { }() #endif -#if !os(Windows) +#if !os(Windows) && !os(WASI) extension Platform { private static var ROOT_USER: UInt32 { 0 } static func getUGIDs(allowEffectiveRootUID: Bool = true) -> (uid: UInt32, gid: UInt32) { @@ -174,7 +174,7 @@ extension Platform { // FIXME: bionic implements this as `return 0;` and does not expose the // function via headers. We should be able to shim this and use the call // if it is available. -#if !os(Android) +#if !os(Android) && !os(WASI) guard issetugid() == 0 else { return nil } #endif if let value = getenv(name) { diff --git a/Sources/FoundationEssentials/String/String+Path.swift b/Sources/FoundationEssentials/String/String+Path.swift index 79bcbfa76..5e42aef4c 100644 --- a/Sources/FoundationEssentials/String/String+Path.swift +++ b/Sources/FoundationEssentials/String/String+Path.swift @@ -450,6 +450,7 @@ extension String { return envVar.standardizingPath } + #if !os(WASI) // WASI does not have user concept // Next, attempt to find the home directory via getpwnam/getpwuid var pass: UnsafeMutablePointer? if let user { @@ -463,6 +464,7 @@ extension String { if let dir = pass?.pointee.pw_dir { return String(cString: dir).standardizingPath } + #endif // Fallback to HOME for the current user if possible if user == nil, let home = getenv("HOME") { From da3bb7dd2556a24f2a8dad512121b75dee248982 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 30 Jul 2024 03:08:45 +0000 Subject: [PATCH 2/2] Throw explicit unsupported error if trying to set user or group on WASI Instead of implicitly ignoring user-given values, we should throw exception to make it clear that those values cannot be set on WASI. --- .../FileManager/FileManager+Files.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift index cbe4f452d..c4caea035 100644 --- a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift +++ b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift @@ -905,8 +905,11 @@ extension _FileManagerImpl { let group = attributes[.groupOwnerAccountName] as? String let groupID = _readFileAttributePrimitive(attributes[.groupOwnerAccountID], as: UInt.self) - #if !os(WASI) // WASI does not have the concept of users or groups if user != nil || userID != nil || group != nil || groupID != nil { + #if os(WASI) + // WASI does not have the concept of users or groups + throw CocoaError.errorWithFilePath(.featureUnsupported, path) + #else // Bias toward userID & groupID - try to prevent round trips to getpwnam if possible. var leaveUnchanged: UInt32 { UInt32(bitPattern: -1) } let rawUserID = userID.flatMap(uid_t.init) ?? user.flatMap(Self._userAccountNameToNumber) ?? leaveUnchanged @@ -914,8 +917,8 @@ extension _FileManagerImpl { if chown(fileSystemRepresentation, rawUserID, rawGroupID) != 0 { throw CocoaError.errorWithFilePath(path, errno: errno, reading: false) } + #endif } - #endif try Self._setCatInfoAttributes(attributes, path: path)