有什么方法可以让我的沙盒Mac应用程序以只读方式访问〜/Library中的文件? [英] Is there any way to give my sandboxed Mac app read only access to files in ~/Library?

查看:125
本文介绍了有什么方法可以让我的沙盒Mac应用程序以只读方式访问〜/Library中的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

谢谢!

解决方案

是的,但是它需要临时例外"权利. 临时"意味着它可能会在将来的某些操作系统版本中消失,但这并不是很大的风险.更大的问题是例外"一词:这意味着您必须证明使用该权利的合理性,否则App Store审阅者可能会拒绝您.

提交一个错误报告,详细说明您认为应该可以做的事情,但是今天如果没有访问~/Library则不能做,并且理想情况下还可以启动有关该主题的论坛讨论.他们可能会建议使用一种解决方法,而不是访问~/Library(甚至使用私有API),在这种情况下,请按照他们说的做.或者他们可能会说暂时使用临时异常,在这种情况下,请执行此操作.否则他们可能没有响应,在这种情况下,您将使用临时异常并用手指交叉.无论如何,请确保您的App Store提交评论笔记中有指向错误报告和/或论坛主题的链接.

您必须手动编辑项目的授权plist来执行此操作,但这并不难.用一个字符串"/Library/"创建一个com.apple.security.temporary-exception.files.home-relative-path.read-only数组.像这样:

<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.你可能想要.请参阅权利密钥参考"文档中的文件访问临时扩展名" .

此外,请注意,您已经可以免费"访问~/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的事实被认为是实现细节",该细节可能有一天会发生变化,这是(除权利之外)另一个必须在苹果提供解决方案之前将其视为临时解决方法的原因.真正解决您更高层次的问题的方法,它可能值得您在评论笔记中提及.

I'm a little confused with the sandbox. Is this possible?

Thanks!

解决方案

Yes, but it requires a "temporary exception" entitlement. "Temporary" means that it may go away in some future version of the OS, but that's not much of a risk. The bigger problem is that word "exception": It means you will have to justify your use of the entitlement, or the App Store reviewers will probably reject you.

File a bug report explaining exactly what it is you think you ought to be able to do, but can't do today without access to ~/Library, and ideally also start a forum thread on the topic. They may suggest a workaround to use instead of accessing ~/Library (maybe even using private APIs), in which case, do what they say. Or they may say to use the temporary exception for now, in which case, do that. Or they may not respond, in which case you use the temporary exception and cross your fingers. In any case, make sure your App Store submission review notes have a link to the bug report and/or forum thread.

You will have to edit your project's entitlements plist manually to do this, but it's not very hard. Create a com.apple.security.temporary-exception.files.home-relative-path.read-only array, with one string, "/Library/". Like this:

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

The extra / at the end is how the sandbox knows you want to access a directory, rather than a file. If you leave it off, you will get access to all files in ~/Library, which is what you asked for, but not to files in (recursive) subdirectories of ~/Library, like, say, ~/Library/LaunchAgents/com.mycompany.myapp.myoldagent.12345678-ABCD-EF00-1234-567890ABCDEF.plist, which is what you probably want. See File Access Temporary Extensions in the Entitlement Key Reference documentation.

Also, notice that you already have access "for free" to certain things under ~/Library, either because they get copied into your container, or indirectly when you use the appropriate APIs instead of using paths. So, there may be a better way to accomplish what you're doing—e.g., to read files left by a previous non-sandboxed version of your app, you might be able to migrate them into the container and read them there.

One more thing: Just having access to ~/Library doesn't change what NSHomeDirectory(), URLsForDirectory:inDomains:, etc. will return--you'll still get ~/Containers/com.mycompany.myproduct/Data/Library instead. Apple's semi-official recommendation for dealing with this is to use BSD APIs to get the user's real home directory, and the simplest way is this:

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

A few notes:

  • It's generally not a good idea to call getpwuid too frequently. The best solution is to call this code once early, and then cache the resulting NSURL.
  • This can obviously also be used to get other users' home (and therefore Library) directories, but the App Store almost certainly won't allow any software that actually tries that.
  • The fact that the library is at ~/Library is considered an "implementation detail" that could change one day, which is another reason (on top of the entitlement) that this has to be considered a temporary workaround until Apple provides a real solution to your higher-level problem, and it might be worth mentioning in your review notes.

这篇关于有什么方法可以让我的沙盒Mac应用程序以只读方式访问〜/Library中的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆