Swift复制目录访问权限时设置URL.fileSecurityKey报错咨询
问题
我尝试将源目录的访问权限复制到目标目录,Finder信息面板显示:
- 源目录权限:「我:读写;所有人:无访问」
- 目标目录原权限:「我:读写;Staff:只读;所有人:只读」
使用以下Swift代码可在目标目录创建文件,但设置URL.fileSecurityKey资源时失败,报错信息为「您没有权限将文件“destination”保存在文件夹“parent”中」。我认为运行在用户权限下的应用应拥有相同权限,且我对两个目录均有读写权限,为何仍出现此问题?
代码:
let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false openPanel.runModal() let source = openPanel.urls[0] openPanel.runModal() var destination = openPanel.urls[0] do { try Data().write(to: destination.appendingPathComponent("asd")) try destination.setResourceValues(source.resourceValues(forKeys: [.fileSecurityKey])) } catch { fatalError(error.localizedDescription) }
分析与解决
核心原因
直接复制完整的fileSecurity会覆盖目标目录的继承权限设置,macOS中目录权限通常会继承父文件夹的属性。当你把源目录「所有人:无访问」的完整权限直接应用到目标目录时,会破坏目标目录原本的继承关系,系统判定该操作超出当前用户权限范围——哪怕你对目标目录本身有读写权限。
另外,fileSecurityKey包含完整的POSIX权限+ACL规则,直接复制会让目标目录丢失原本从父目录继承的ACL条目,这些条目可能包含系统或其他用户的必要权限设置,触发系统的权限保护机制。
解决方法
不要直接复制完整的fileSecurity,提取并复制核心权限部分即可:
- 从源目录获取POSIX权限、所有者及组所有者信息
- 仅将这些核心权限应用到目标目录,保留目标目录原本的继承ACL规则
修改后的代码示例:
let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false openPanel.runModal() let source = openPanel.urls[0] openPanel.runModal() let destination = openPanel.urls[0] do { // 创建测试文件验证基础读写权限 try Data().write(to: destination.appendingPathComponent("asd")) // 获取源目录核心权限信息 let sourceValues = try source.resourceValues(forKeys: [.posixPermissionsKey, .ownerAccountIDKey, .groupOwnerAccountIDKey]) // 构建目标目录权限设置(仅覆盖核心项,保留继承属性) var destValues = URLResourceValues() destValues.posixPermissions = sourceValues.posixPermissions destValues.ownerAccountID = sourceValues.ownerAccountID destValues.groupOwnerAccountID = sourceValues.groupOwnerAccountID // 应用权限设置 try destination.setResourceValues(destValues) } catch { fatalError(error.localizedDescription) }
补充说明
- 若确实需要复制ACL规则,不要直接覆盖,先获取目标目录现有ACL,再合并源目录的必要条目,避免破坏继承关系
- macOS权限系统(尤其是ACL)会结合父目录继承规则,直接替换完整
fileSecurity会触发系统安全校验,即使是目录所有者也可能被阻止
内容的提问来源于stack exchange,提问作者Nickkk
相关产品推荐
相关产品推荐

