问题:
请注意,出于这个问题的目的,我将假设目录是一种特殊的文件。
此外,我会假设(如果我错了,请纠正我),对目录的写权限包括在所述目录中创建新文件的权利。
std::filesystem::perms
列出了以下类型的权限,每种权限适用于三种操作类型read
,write
和execute
:
owner
:文件的所有者 。group
:文件的用户组 。others
:每个人? (完全不确定;如果错误,请更正。)现在,可以很容易地看出,如果有人想知道正在运行的程序是否具有给定的权限,那么从这些信息中得出这些信息并非易事:
有趣的是,库中似乎没有任何函数,它们对应于以下函数声明:
enum FileAction { READ = 1, WRITE = 2, RW = READ|WRITE };
bool canDo(const std::filesystem::path & path, FileAction action);
那么如何实现这样的功能呢?
当然,好的旧的C ++之前的方法是尝试开始读/写,如果失败则捕获异常。我想认为Filesystem库必须提供更优雅的解决方案。
我对适用于Windows(XP +)和Linux的答案很感兴趣。请注意,如果您的答案仅适用于一个(即使有人希望确实存在并且可以找到一个通用答案)。
使用案例(姗姗来迟加入"你不应该问这个"答案。)
确定游戏开始是否其自己的目录处于有效状态:毕竟,无论如何它都会失败,无论如何都要运行。
我们可以假设没有其他程序会弄乱应用程序的安装目录。如果我们不能,那么用户及其系统比故障游戏和我们不关心有更大的问题。
这通常是个人计算机中物理磁盘上的本地目录,在操作期间不会失败(同样,如果我们停止关怀)。用户和任何其他程序都不会尝试将文件移出我们的安装目录或删除它们或窃取我们的权限,因为这是愚蠢的(或故意的)因此,如果发生这种情况,我们停止关怀。
只要我们还在关注,我们希望提供尽力而为又名贪婪算法又名有根据的猜测我们可以期待成功运行。
用户可能在处理其操作系统时非专业,而需要提示以提供工作环境。我们希望提供我们可以提供的所有提示,然后停止关怀,因为我们是一个应用程序,而不是操作系统,当然不是系统管理员。
我们想要帮助用户,只要付出一点努力就可以帮助,因为我们很好。我们不是撒玛利亚人,也不是超级英雄,只是很好。我们也没有兴趣尝试拦截用户可能故意做的恶作剧,因为任何由此产生的麻烦都是他们自己的错误因此我们停止关怀。
游戏的完善的做法以启发式方式检查其安装目录的完整性。 Steam为所有通过它安装的游戏提供此服务。 “星际迷航”,“英雄联盟”,“Warframe”等发射器都有相同的发射器。
这些游戏通常通过计算(通过读取)其文件的哈希值并将它们与已知的有效哈希值进行比较来检查文件完整性。
其中几乎所有文件都是供用户修改的游戏,例如Dwarf Fortress不能这样做。它可以,但是检查必须读取的文件的读取权限,以及写入必须写入的文件的权限。再说一遍:在游戏运行时没有目的来操纵这些权利,因此不应该假设它发生。
答案 0 :(得分:3)
"只需尝试I / O并处理故障"仍然是最好的方法,出于多种原因(按照你在现实世界中遇到它们的速度大致递减顺序):
预测故障需要重现操作系统的整个访问控制逻辑,这很可能与版本有关。不要重新发明轮子。
即使完美地完成预测也只会告诉您 now ,而不是实际尝试I / O操作时会发生什么。文件系统是共享资源,权限可以更改。这种竞争条件如此常见,它有自己的名字:TOCTOU(支票时间 - 使用时间)
由于许多与权限无关的其他原因导致I / O仍然失败(驱动器被用户断开,网络断开,另一个进程占用了所有可用空间)。
最终,您无法避免故障处理,同时执行权限评估和故障处理会增加复杂性而不会带来任何好处。
我不知道你为什么会把异常带入混合中 - 只需以通常的方式打开文件(fstream
或fopen
)并检查结果。 fstream
会为failbit
设置一个对象,fopen
会提供NULL
,在这两种情况下errno
都可能有助于诊断原因。
答案 1 :(得分:0)
当然,好的旧前C ++ 17方式就是试着开始 读/写,如果失败则捕获异常。我想要 认为Filesystem库必须提供更优雅的功能 溶液
没有“更优雅的解决方案”。
任何此类声称的“解决方案”都容易受到TOCTOU race condition的影响。
您无法可靠地检查是否允许执行X,然后尝试在单独的操作中执行X.