From bca2f46d080d2d79332143d36df44350e63c6770 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sat, 4 Jan 2025 07:39:59 +0900 Subject: [PATCH] [6.1] Fix WASI build of `_copyDirectoryMetadata` (#1099) * Fix WASI build of `_copyDirectoryMetadata` (#1094) Extended attributes don't exist in WASI, so we need to exclude the use of xattr-related APIs including `flistxattr`. * Follow-up fixes to make it work with wasi-libc (#1095) * Gate `fchown` and `fchmod` calls behind `os(WASI)` They are not available on WASI, so we gate them behind `os(WASI)`. * Add missing constant shims for wasi-libc * Use `futimens` instead of legacy `futimes` wasi-libc does not provide `futimes` as it is a legacy function. https://github.com/WebAssembly/wasi-libc/blob/574b88da481569b65a237cb80daf9a2d5aeaf82d/libc-top-half/musl/include/sys/time.h#L34 * Don't try to set extended attributes on Android (#1106) Normal users don't have permission to change these, even for their own files. --------- Co-authored-by: finagolfin --- .../FileManager/FileOperations.swift | 12 +++++++++--- .../FoundationEssentials/WASILibc+Extensions.swift | 9 +++++++++ Sources/_FoundationCShims/include/platform_shims.h | 4 ++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Sources/FoundationEssentials/FileManager/FileOperations.swift b/Sources/FoundationEssentials/FileManager/FileOperations.swift index 83d131a5b..b29e7121a 100644 --- a/Sources/FoundationEssentials/FileManager/FileOperations.swift +++ b/Sources/FoundationEssentials/FileManager/FileOperations.swift @@ -911,6 +911,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) // Copy extended attributes var size = flistxattr(srcFD, nil, 0) if size > 0 { @@ -936,28 +937,33 @@ enum _FileOperations { } } } + #endif var statInfo = stat() if fstat(srcFD, &statInfo) == 0 { + #if !os(WASI) // WASI doesn't have fchown for now // Copy owner/group if fchown(dstFD, statInfo.st_uid, statInfo.st_gid) != 0 { try delegate.throwIfNecessary(errno, srcPath(), dstPath()) } + #endif // Copy modification date - let value = timeval(tv_sec: statInfo.st_mtim.tv_sec, tv_usec: statInfo.st_mtim.tv_nsec / 1000) + let value = statInfo.st_mtim var tv = (value, value) try withUnsafePointer(to: &tv) { - try $0.withMemoryRebound(to: timeval.self, capacity: 2) { - if futimes(dstFD, $0) != 0 { + try $0.withMemoryRebound(to: timespec.self, capacity: 2) { + if futimens(dstFD, $0) != 0 { try delegate.throwIfNecessary(errno, srcPath(), dstPath()) } } } + #if !os(WASI) // WASI doesn't have fchmod for now // Copy permissions if fchmod(dstFD, statInfo.st_mode) != 0 { try delegate.throwIfNecessary(errno, srcPath(), dstPath()) } + #endif } else { try delegate.throwIfNecessary(errno, srcPath(), dstPath()) } diff --git a/Sources/FoundationEssentials/WASILibc+Extensions.swift b/Sources/FoundationEssentials/WASILibc+Extensions.swift index 351fe19f2..44f3f936a 100644 --- a/Sources/FoundationEssentials/WASILibc+Extensions.swift +++ b/Sources/FoundationEssentials/WASILibc+Extensions.swift @@ -49,5 +49,14 @@ internal var O_TRUNC: Int32 { internal var O_WRONLY: Int32 { return _platform_shims_O_WRONLY() } +internal var O_RDONLY: Int32 { + return _platform_shims_O_RDONLY() +} +internal var O_DIRECTORY: Int32 { + return _platform_shims_O_DIRECTORY() +} +internal var O_NOFOLLOW: Int32 { + return _platform_shims_O_NOFOLLOW() +} #endif // os(WASI) diff --git a/Sources/_FoundationCShims/include/platform_shims.h b/Sources/_FoundationCShims/include/platform_shims.h index 6bc0a0e15..e02b58177 100644 --- a/Sources/_FoundationCShims/include/platform_shims.h +++ b/Sources/_FoundationCShims/include/platform_shims.h @@ -102,6 +102,10 @@ static inline int32_t _platform_shims_O_CREAT(void) { return O_CREAT; } static inline int32_t _platform_shims_O_EXCL(void) { return O_EXCL; } static inline int32_t _platform_shims_O_TRUNC(void) { return O_TRUNC; } static inline int32_t _platform_shims_O_WRONLY(void) { return O_WRONLY; } +static inline int32_t _platform_shims_O_RDONLY(void) { return O_RDONLY; } +static inline int32_t _platform_shims_O_DIRECTORY(void) { return O_DIRECTORY; } +static inline int32_t _platform_shims_O_NOFOLLOW(void) { return O_NOFOLLOW; } + #endif #endif /* CSHIMS_PLATFORM_SHIMS */