|
| 1 | +From 1f5e0a8cc6e45e6be7a6d983877dbd602e5c0ff8 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Yuta Saito < [email protected]> |
| 3 | +Date: Fri, 2 Aug 2024 01:23:13 +0900 |
| 4 | +Subject: [PATCH] Guard out user/group related code on WASI (#783) |
| 5 | + |
| 6 | +* Guard out user/group related code on WASI |
| 7 | + |
| 8 | +This change guards out the user/group related code on WASI, as WASI does |
| 9 | +not have the concept of users or groups. |
| 10 | + |
| 11 | +* Throw explicit unsupported error if trying to set user or group on WASI |
| 12 | + |
| 13 | +Instead of implicitly ignoring user-given values, we should throw |
| 14 | +exception to make it clear that those values cannot be set on WASI. |
| 15 | +--- |
| 16 | + Sources/FoundationEssentials/Data/Data+Writing.swift | 2 ++ |
| 17 | + .../FoundationEssentials/FileManager/FileManager+Files.swift | 5 +++++ |
| 18 | + .../FileManager/FileManager+Utilities.swift | 2 +- |
| 19 | + .../FoundationEssentials/FileManager/FileOperations.swift | 2 ++ |
| 20 | + Sources/FoundationEssentials/Platform.swift | 4 ++-- |
| 21 | + Sources/FoundationEssentials/String/String+Path.swift | 2 ++ |
| 22 | + 6 files changed, 14 insertions(+), 3 deletions(-) |
| 23 | + |
| 24 | +diff --git a/Sources/FoundationEssentials/Data/Data+Writing.swift b/Sources/FoundationEssentials/Data/Data+Writing.swift |
| 25 | +index 1e75b43..78a9a98 100644 |
| 26 | +--- a/Sources/FoundationEssentials/Data/Data+Writing.swift |
| 27 | ++++ b/Sources/FoundationEssentials/Data/Data+Writing.swift |
| 28 | +@@ -516,6 +516,7 @@ private func writeToFileAux(path inPath: PathOrURL, buffer: UnsafeRawBufferPoint |
| 29 | + |
| 30 | + cleanupTemporaryDirectory(at: temporaryDirectoryPath) |
| 31 | + |
| 32 | ++#if !os(WASI) // WASI does not support fchmod for now |
| 33 | + if let mode { |
| 34 | + // Try to change the mode if the path has not changed. Do our best, but don't report an error. |
| 35 | + #if FOUNDATION_FRAMEWORK |
| 36 | +@@ -539,6 +540,7 @@ private func writeToFileAux(path inPath: PathOrURL, buffer: UnsafeRawBufferPoint |
| 37 | + fchmod(fd, mode) |
| 38 | + #endif |
| 39 | + } |
| 40 | ++#endif // os(WASI) |
| 41 | + } |
| 42 | + } |
| 43 | + } |
| 44 | +diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift |
| 45 | +index b8cd50a..943ac9e 100644 |
| 46 | +--- a/Sources/FoundationEssentials/FileManager/FileManager+Files.swift |
| 47 | ++++ b/Sources/FoundationEssentials/FileManager/FileManager+Files.swift |
| 48 | +@@ -928,6 +928,10 @@ extension _FileManagerImpl { |
| 49 | + let groupID = _readFileAttributePrimitive(attributes[.groupOwnerAccountID], as: UInt.self) |
| 50 | + |
| 51 | + if user != nil || userID != nil || group != nil || groupID != nil { |
| 52 | ++ #if os(WASI) |
| 53 | ++ // WASI does not have the concept of users or groups |
| 54 | ++ throw CocoaError.errorWithFilePath(.featureUnsupported, path) |
| 55 | ++ #else |
| 56 | + // Bias toward userID & groupID - try to prevent round trips to getpwnam if possible. |
| 57 | + var leaveUnchanged: UInt32 { UInt32(bitPattern: -1) } |
| 58 | + let rawUserID = userID.flatMap(uid_t.init) ?? user.flatMap(Self._userAccountNameToNumber) ?? leaveUnchanged |
| 59 | +@@ -935,6 +939,7 @@ extension _FileManagerImpl { |
| 60 | + if chown(fileSystemRepresentation, rawUserID, rawGroupID) != 0 { |
| 61 | + throw CocoaError.errorWithFilePath(path, errno: errno, reading: false) |
| 62 | + } |
| 63 | ++ #endif |
| 64 | + } |
| 65 | + |
| 66 | + try Self._setCatInfoAttributes(attributes, path: path) |
| 67 | +diff --git a/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift b/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift |
| 68 | +index 9bac967..4f42f19 100644 |
| 69 | +--- a/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift |
| 70 | ++++ b/Sources/FoundationEssentials/FileManager/FileManager+Utilities.swift |
| 71 | +@@ -274,7 +274,7 @@ extension _FileManagerImpl { |
| 72 | + } |
| 73 | + #endif |
| 74 | + |
| 75 | +-#if !os(Windows) |
| 76 | ++#if !os(Windows) && !os(WASI) |
| 77 | + static func _userAccountNameToNumber(_ name: String) -> uid_t? { |
| 78 | + name.withCString { ptr in |
| 79 | + getpwnam(ptr)?.pointee.pw_uid |
| 80 | +diff --git a/Sources/FoundationEssentials/FileManager/FileOperations.swift b/Sources/FoundationEssentials/FileManager/FileOperations.swift |
| 81 | +index 528a7c9..8734fc0 100644 |
| 82 | +--- a/Sources/FoundationEssentials/FileManager/FileOperations.swift |
| 83 | ++++ b/Sources/FoundationEssentials/FileManager/FileOperations.swift |
| 84 | +@@ -874,12 +874,14 @@ enum _FileOperations { |
| 85 | + } |
| 86 | + defer { close(dstfd) } |
| 87 | + |
| 88 | ++ #if !os(WASI) // WASI doesn't have fchmod for now |
| 89 | + // Set the file permissions using fchmod() instead of when open()ing to avoid umask() issues |
| 90 | + let permissions = fileInfo.st_mode & ~S_IFMT |
| 91 | + guard fchmod(dstfd, permissions) == 0 else { |
| 92 | + try delegate.throwIfNecessary(errno, String(cString: srcPtr), String(cString: dstPtr)) |
| 93 | + return |
| 94 | + } |
| 95 | ++ #endif |
| 96 | + |
| 97 | + if fileInfo.st_size == 0 { |
| 98 | + // no copying required |
| 99 | +diff --git a/Sources/FoundationEssentials/Platform.swift b/Sources/FoundationEssentials/Platform.swift |
| 100 | +index 9c3f2d7..4549a45 100644 |
| 101 | +--- a/Sources/FoundationEssentials/Platform.swift |
| 102 | ++++ b/Sources/FoundationEssentials/Platform.swift |
| 103 | +@@ -114,7 +114,7 @@ private let _cachedUGIDs: (uid_t, gid_t) = { |
| 104 | + }() |
| 105 | + #endif |
| 106 | + |
| 107 | +-#if !os(Windows) |
| 108 | ++#if !os(Windows) && !os(WASI) |
| 109 | + extension Platform { |
| 110 | + private static var ROOT_USER: UInt32 { 0 } |
| 111 | + static func getUGIDs(allowEffectiveRootUID: Bool = true) -> (uid: UInt32, gid: UInt32) { |
| 112 | +@@ -175,7 +175,7 @@ extension Platform { |
| 113 | + // FIXME: bionic implements this as `return 0;` and does not expose the |
| 114 | + // function via headers. We should be able to shim this and use the call |
| 115 | + // if it is available. |
| 116 | +-#if !os(Android) |
| 117 | ++#if !os(Android) && !os(WASI) |
| 118 | + guard issetugid() == 0 else { return nil } |
| 119 | + #endif |
| 120 | + if let value = getenv(name) { |
| 121 | +diff --git a/Sources/FoundationEssentials/String/String+Path.swift b/Sources/FoundationEssentials/String/String+Path.swift |
| 122 | +index 477d5d3..aaf62d1 100644 |
| 123 | +--- a/Sources/FoundationEssentials/String/String+Path.swift |
| 124 | ++++ b/Sources/FoundationEssentials/String/String+Path.swift |
| 125 | +@@ -452,6 +452,7 @@ extension String { |
| 126 | + return envVar.standardizingPath |
| 127 | + } |
| 128 | + |
| 129 | ++ #if !os(WASI) // WASI does not have user concept |
| 130 | + // Next, attempt to find the home directory via getpwnam/getpwuid |
| 131 | + var pass: UnsafeMutablePointer<passwd>? |
| 132 | + if let user { |
| 133 | +@@ -465,6 +466,7 @@ extension String { |
| 134 | + if let dir = pass?.pointee.pw_dir { |
| 135 | + return String(cString: dir).standardizingPath |
| 136 | + } |
| 137 | ++ #endif |
| 138 | + |
| 139 | + // Fallback to HOME for the current user if possible |
| 140 | + if user == nil, let home = getenv("HOME") { |
| 141 | +-- |
| 142 | +2.43.2 |
| 143 | + |
0 commit comments