有没有办法让我的沙盒 Mac 应用程序只读访问 ~/Library 中的文件?

Posted

技术标签:

【中文标题】有没有办法让我的沙盒 Mac 应用程序只读访问 ~/Library 中的文件?【英文标题】:Is there any way to give my sandboxed Mac app read only access to files in ~/Library? 【发布时间】:2012-06-08 15:58:46 【问题描述】:

我对沙盒有点困惑。这可能吗?

谢谢!

【问题讨论】:

是否可以使用“com.apple.security.temporary-exception.files.absolute-path.read-write 获得对我的应用程序的写权限”启用对指定文件的读/写访问权限或指定绝对路径的目录。” 为什么有 10 个用户喜欢这个但只有 8 个用户点赞...? 【参考方案1】:

是的,但它需要“临时例外”权利。 “临时”意味着它可能会在操作系统的某些未来版本中消失,但这并没有太大的风险。更大的问题是“例外”这个词:这意味着您必须证明您使用该权利的合理性,否则 App Store 审核者可能会拒绝您。

提交一份错误报告,准确解释您认为自己应该能够做什么,但如果不能访问~/Library,今天就无法做到这一点,理想情况下还可以在该主题上启动一个论坛帖子。他们可能会建议使用一种解决方法,而不是访问~/Library(甚至可能使用私有 API),在这种情况下,按照他们所说的去做。或者他们可能会说暂时使用临时例外,在这种情况下,这样做。或者他们可能没有响应,在这种情况下,您使用临时例外并交叉手指。在任何情况下,请确保您的 App Store 提交评论注释包含指向错误报告和/或论坛主题的链接。

您必须手动编辑项目的权利 plist 才能做到这一点,但这并不难。创建一个com.apple.security.temporary-exception.files.home-relative-path.read-only 数组,其中包含一个字符串"/Library/"。像这样:

<key>com.apple.security.temporary-exception.files.home-relative-path.read-only</key>
<array>
    <string>/Library/</string>
</array>

末尾的额外/ 是沙盒如何知道您要访问目录而不是文件的方式。如果你把它关掉,你将可以访问~/Library 中的所有文件,这是你要求的,但不能访问~/Library 的(递归)子目录中的文件,比如~/Library/LaunchAgents/com.mycompany.myapp.myoldagent.12345678-ABCD-EF00-1234-567890ABCDEF.plist,这就是你可能想要。请参阅权利密钥参考文档中的File Access Temporary Extensions。

另外,请注意,您已经可以“免费”访问 ~/Library 下的某些内容,因为它们被复制到您的容器中,或者在您使用适当的 API 而不是使用路径时间接访问。因此,可能有更好的方法来完成您正在做的事情——例如,读取您的应用程序以前的非沙盒版本留下的文件,您可能能够将它们迁移到容器中并在那里读取它们。

还有一件事:仅仅访问 ~/Library 并不会改变 NSHomeDirectory()URLsForDirectory:inDomains: 等将返回的内容——您仍然会得到 ~/Containers/com.mycompany.myproduct/Data/Library。 Apple 的半官方建议是使用 BSD API 来获取用户的真实主目录,最简单的方法是:

const char *home = getpwuid(getuid())->pw_dir;
NSString *path = [[NSFileManager defaultManager] 
                  stringWithFileSystemRepresentation:home
                  length:strlen(home)];
NSURL *url = [NSURL fileURLWithPath:path isDirectory:YES];

几点说明:

过于频繁地拨打getpwuid 通常不是一个好主意。最好的解决方案是提前调用此代码一次,然后缓存生成的NSURL。 这显然也可用于获取其他用户的主目录(因此也可用于获取 Library),但 App Store 几乎肯定不会允许任何实际尝试这样做的软件。 库位于~/Library 的事实被认为是一个“实施细节”,可能有一天会改变,这是另一个原因(在权利之上)这必须被视为临时解决方法,直到 Apple 提供真正解决您更高级别问题的方法,并且可能值得在您的评论笔记中提及。

【讨论】:

赞成,尽管您提出的使用getpwent()-&gt;pw_dir 的解决方案为我返回/var/virusmails 这对我有用:getpwnam([NSUserName() UTF8String])-&gt;pw_dir 对不起; “正确”的方式是 getpwuid(getuid()),而不是 getpwent()(返回第一个条目)。由 Apple 的一位沙盒工程师在论坛上认可的原始解决方案有同样的错误,后来被纠正,不知何故错误的版本卡在我的脑海里。我已经更新了我的答案。无论如何,getpwnam 和 getpwuid 一样好,所以你可以坚持那些已经为你工作的东西。 @anka:嗯,他要求“~/Library 中的文件”,但你是对的,他几乎肯定想要~/Library 的某个子目录 下的文件。

以上是关于有没有办法让我的沙盒 Mac 应用程序只读访问 ~/Library 中的文件?的主要内容,如果未能解决你的问题,请参考以下文章

谷歌分析沙盒

Mac App Store 登录中的沙盒用户更改

在其他 Mac 上的沙盒中测试 Mac Appstore 的 IAP

Mac 应用程序沙盒和 forkpty()

有没有办法重置我的 GameCenter 沙盒帐户的成就进度?

如何检查用户选择的文件是不是我的沙盒应用程序具有写入权限?