c++ - 确定程序本身是否对文件具有一定访问权限的最简洁方法是什么?

标签 c++ filesystems std file-access c++17

问题:

请注意,出于这个问题的目的,我将假定目录是一种特殊的文件。

此外,我将假定(如果我错了,请纠正我),对目录的写权限包括在该目录中创建新文件的权限。
std::filesystem::perms列出以下几种权限,每种权限分别针对readwriteexecute三种操作类型:

  • owner:文件的所有者。
  • group:文件的用户组。
  • others:每个人? (对此完全不确定;如果有误,请更正。)

  • 现在,可以很容易地看出,如果希望知道正在运行的程序是否具有给定的权限,则从这些信息中获取这些信息是很重要的:
  • 程序的用户是文件的用户吗?
  • 文件的任何用户组是该程序的用户组之一还是其​​子级?

  • 有趣的是,库中似乎不存在任何函数,该函数对应于以下函数声明:
    enum FileAction { READ = 1, WRITE = 2, RW = READ|WRITE };
    
    bool canDo(const std::filesystem::path & path, FileAction action);
    

    那么如何实现这种功能?

    当然,旧的C++ 17之前的好方法是尝试开始读/写并在失败时捕获异常。我想认为Filesystem库必须提供更优雅的解决方案。

    我对适用于Windows(XP +)和Linux的答案感兴趣。请注意,如果您的答案仅适用于一个答案(即使有人希望确实存在一个普遍答案并可以找到它)。

    用例:(已添加到病房中,反对“您不应该问这个”答案。)

    在游戏开始时确定其自己的目录是否处于有效状态:毕竟,如果它仍然会失败,则无需运行。

    我们可以假设没有其他程序会干扰应用程序的安装目录。如果不能,那么用户和他们的系统将比故障游戏产生更大的问题,我们不在乎。

    这通常是个人计算机物理磁盘上的本地目录,在操作过程中不会失败(同样,如果我们停止维护,则不会发生故障)。用户和任何其他程序都不会尝试将文件移出安装目录,也不会删除文件或窃取我们的权限,因为这是愚蠢的(或故意的),因此,如果发生这种情况,我们将不再关心。

    只要我们仍在乎,我们希望就是否可以成功运行提供尽力而为的贪婪算法,也就是有根据的猜测。

    用户在处理其操作系统时可能不是专业人士,因此需要提示以提供工作环境。我们希望提供所有可能的提示,然后再停止关怀,因为我们是一个应用程序,不是操作系统,当然也不是系统管理员。

    如果我们愿意帮助您,请提供帮助,因为我们很高兴。我们不是撒马利亚人,也不是 super 英雄,只是很好。我们也没有兴趣尝试拦截用户可能故意承担的恶作剧,因为这会导致任何麻烦都是他们自己的错,因此我们不再关心。

    对于游戏来说,完善的做法是启发式检查其安装目录的完整性。 Steam将其作为通过它安装的所有游戏的服务。 《星际迷航》,《英雄联盟》,《 war 机器》都具有相同的发射器。

    这些游戏通常通过计算(通过读取)文件的哈希并将它们与已知的有效哈希进行比较来检查文件的完整性。

    几乎所有文件都供用户修改的游戏(例如Dwarf Fortress)无法做到。但是,它可以检查必须读取的文件读取权限和必须写入的文件写入权限。再说一次:在游戏运行时操纵这些权利是没有目的的,因此不应假定它发生了。

    最佳答案

    出于多种原因(“在现实世界中,遇到这些错误的速度大致按降序排列”),“仅尝试I / O并处理故障”仍然是最好的方法:

  • 预测失败需要重现OS的整个访问控制逻辑,这很可能与版本有关。不要重新发明轮子。
  • 即使成功完成,预测失败也只能告诉您现在的情况,而不是实际尝试I / O操作时会发生的情况。文件系统是共享资源,权限可以更改。这种竞争条件非常普遍,它有自己的名称:TOCTOU(检查时间-使用时间)
  • 由于与许可无关的多种其他原因,I / O仍可能失败(驱动器已被用户断开连接,网络出现故障,另一个进程耗尽了所有可用空间)。

  • 最终,您无法避免失败处理,而同时进行权限评估和失败处理会增加复杂性而没有任何好处。

    我不知道您为什么将异常添加到混合中-只需以通常的方式(fstreamfopen)打开文件并检查结果即可。 fstream将给出设置了failbit的对象,fopen将给出NULL,在两种情况下errno都可以帮助诊断原因。

    关于c++ - 确定程序本身是否对文件具有一定访问权限的最简洁方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37754910/

    相关文章:

    c++ - 唯一指针映射,带有原始指针的 .at()

    c++ - 当前线程的线程关联掩码更改有什么好处?

    c++ - 查找库的 "name"(-L -l 开关)

    windows - 在 unix (linux/osx) 中创建的符号链接(symbolic link)在 windows 中仍然有效吗?

    php - 如何在 PHP 中进行 fsync 或 fdatasync?

    c++ - 对 std::map 中元素的引用是否可以失效?

    c++ - 为什么 int a; a = std::max(a, x) 不发出 "uninitialized"警告

    c++ - 我可以从内存流加载库吗?

    c# - 原子检查文件是否存在并打开它

    c++ - 哪些低级 Windows 特定函数用于在 Windows 中实现 std::thread/boost::thread/pthread?