@@ -1113,43 +1113,75 @@ nonisolated enum TerminationSaveCoordinator {
11131113 leaf: String ,
11141114 fallback: URL
11151115 ) -> URL {
1116- currentArtifactURL (
1116+ resolvedArtifactURL (
11171117 parentDescriptor: parentDescriptor,
1118- leaf: leaf
1118+ leaf: leaf,
1119+ fallback: fallback
11191120 ) ?? fallback
11201121 }
11211122
1123+ private static func resolvedArtifactURL(
1124+ parentDescriptor: Int32 ,
1125+ leaf: String ,
1126+ fallback: URL ?
1127+ ) -> URL ? {
1128+ if let fallback,
1129+ fallback. lastPathComponent == leaf,
1130+ directoryPathMatches (
1131+ parentDescriptor: parentDescriptor,
1132+ url: fallback. deletingLastPathComponent ( )
1133+ ) {
1134+ return fallback
1135+ }
1136+ return currentArtifactURL (
1137+ parentDescriptor: parentDescriptor,
1138+ leaf: leaf
1139+ )
1140+ }
1141+
11221142 private static func currentArtifactURL(
11231143 parentDescriptor: Int32 ,
11241144 leaf: String
11251145 ) -> URL ? {
1126- var path = [ CChar] (
1127- repeating: 0 ,
1128- count: 4 * Int( MAXPATHLEN)
1129- )
1130- guard let handle = Darwin . dlopen ( nil , RTLD_LAZY | RTLD_LOCAL) else {
1131- return nil
1146+ var descriptorInfo = vnode_fdinfowithpath ( )
1147+ let expectedSize = MemoryLayout< vnode_fdinfowithpath> . size
1148+ guard expectedSize <= Int ( Int32 . max) else { return nil }
1149+ let result = withUnsafeMutablePointer ( to: & descriptorInfo) { pointer in
1150+ Darwin . proc_pidfdinfo (
1151+ Darwin . getpid ( ) ,
1152+ parentDescriptor,
1153+ PROC_PIDFDVNODEPATHINFO,
1154+ pointer,
1155+ Int32 ( expectedSize)
1156+ )
11321157 }
1133- defer { Darwin . dlclose ( handle) }
1134- guard let symbol = Darwin . dlsym ( handle, " fcntl " ) else {
1158+ guard result == Int32 ( expectedSize) else { return nil }
1159+ let currentPath = withUnsafeBytes (
1160+ of: & descriptorInfo. pvip. vip_path
1161+ ) { buffer -> String ? in
1162+ let path = buffer. bindMemory ( to: CChar . self)
1163+ let terminator = path. firstIndex ( of: 0 ) ?? path. endIndex
1164+ guard terminator != path. startIndex else { return nil }
1165+ let pathBytes = path [ ..< terminator] . map ( UInt8 . init ( bitPattern: ) )
1166+ return String ( bytes: pathBytes, encoding: . utf8)
1167+ }
1168+ guard let currentPath else {
11351169 return nil
11361170 }
1137- typealias FcntlPath = @convention ( c) (
1138- Int32 ,
1139- Int32 ,
1140- UnsafeMutableRawPointer ?
1141- ) -> Int32
1142- let fcntlPath = unsafeBitCast ( symbol, to: FcntlPath . self)
1143- let result = path. withUnsafeMutableBytes { buffer in
1144- fcntlPath ( parentDescriptor, F_GETPATH, buffer. baseAddress)
1145- }
1146- guard result == 0 else { return nil }
1147- let terminator = path. firstIndex ( of: 0 ) ?? path. endIndex
1148- let pathBytes = path [ ..< terminator] . map ( UInt8 . init ( bitPattern: ) )
1149- guard let currentPath = String ( bytes: pathBytes, encoding: . utf8) else {
1171+ let currentParentURL = URL (
1172+ fileURLWithPath: currentPath,
1173+ isDirectory: true
1174+ )
1175+ var descriptorStatus = stat ( )
1176+ var pathStatus = stat ( )
1177+ guard Darwin . fstat ( parentDescriptor, & descriptorStatus) == 0 ,
1178+ ( descriptorStatus. st_mode & S_IFMT) == S_IFDIR,
1179+ Darwin . lstat ( currentParentURL. path, & pathStatus) == 0 ,
1180+ ( pathStatus. st_mode & S_IFMT) == S_IFDIR,
1181+ sameObject ( descriptorStatus, pathStatus) else {
11501182 return nil
11511183 }
1152- return URL ( fileURLWithPath : currentPath )
1184+ return currentParentURL
11531185 . appendingPathComponent ( leaf)
11541186 }
11551187
@@ -2034,21 +2066,23 @@ nonisolated enum TerminationSaveCoordinator {
20342066 if errno == ENOENT { return . removed }
20352067 return . failed(
20362068 message: " Could not quarantine an artifact before cleanup " ,
2037- retainedURL: currentArtifactURL (
2069+ retainedURL: resolvedArtifactURL (
20382070 parentDescriptor: parentDescriptor,
2039- leaf: leaf
2040- ) ?? fallbackOriginalURL
2071+ leaf: leaf,
2072+ fallback: fallbackOriginalURL
2073+ )
20412074 )
20422075 }
20432076 do {
20442077 try synchronizeDirectory ( parentDescriptor)
20452078 } catch {
20462079 return . failed(
20472080 message: " Could not make artifact quarantine durable " ,
2048- retainedURL: currentArtifactURL (
2081+ retainedURL: resolvedArtifactURL (
20492082 parentDescriptor: parentDescriptor,
2050- leaf: cleanupLeaf
2051- ) ?? fallbackCleanupURL
2083+ leaf: cleanupLeaf,
2084+ fallback: fallbackCleanupURL
2085+ )
20522086 )
20532087 }
20542088 guard regularFileMatches (
@@ -2067,19 +2101,23 @@ nonisolated enum TerminationSaveCoordinator {
20672101 }
20682102 return . failed(
20692103 message: " An artifact changed identity during cleanup " ,
2070- retainedURL: currentArtifactURL (
2104+ retainedURL: resolvedArtifactURL (
20712105 parentDescriptor: parentDescriptor,
2072- leaf: restored ? leaf : cleanupLeaf
2073- ) ?? ( restored ? fallbackOriginalURL : fallbackCleanupURL)
2106+ leaf: restored ? leaf : cleanupLeaf,
2107+ fallback: restored
2108+ ? fallbackOriginalURL
2109+ : fallbackCleanupURL
2110+ )
20742111 )
20752112 }
20762113 guard Darwin . unlinkat ( parentDescriptor, cleanupLeaf, 0 ) == 0 else {
20772114 return . failed(
20782115 message: " Could not unlink a quarantined artifact " ,
2079- retainedURL: currentArtifactURL (
2116+ retainedURL: resolvedArtifactURL (
20802117 parentDescriptor: parentDescriptor,
2081- leaf: cleanupLeaf
2082- ) ?? fallbackCleanupURL
2118+ leaf: cleanupLeaf,
2119+ fallback: fallbackCleanupURL
2120+ )
20832121 )
20842122 }
20852123 do {
0 commit comments