C++ File stat()vs access()检查目录的权限

C++ File stat()vs access()检查目录的权限,c++,file-io,stat,C++,File Io,Stat,我已经分别成功地使用了stat()和access()来确定用户是否具有对目录的读或读/写访问权限 我的问题是: -有没有更好的方法?我看到了很多使用stat的示例,但就我而言,access似乎更轻量级,更符合我的目的。 -是否存在任何一个或另一个问题(如安全)? -我的方法有什么问题吗 以下是一些伪代码(从内存重新创建,不进行编译): 这两种方法都能满足您的需求access()是一个更干净的包装器 只是要注意,你这样做是在创造一场比赛。在调用stat()/access()和实际尝试使用目录时,权

我已经分别成功地使用了
stat()
access()
来确定用户是否具有对目录的读或读/写访问权限

我的问题是: -有没有更好的方法?我看到了很多使用
stat
的示例,但就我而言,access似乎更轻量级,更符合我的目的。
-是否存在任何一个或另一个问题(如安全)? -我的方法有什么问题吗

以下是一些伪代码(从内存重新创建,不进行编译):


这两种方法都能满足您的需求<如果您不打算对填充的stat结构做任何事情,那么code>access()是一个更干净的包装器

只是要注意,你这样做是在创造一场比赛。在调用
stat()/access()
和实际尝试使用目录时,权限可以更改。该死,这个目录甚至可以在那个时候被删除并重新创建


最好尝试打开所需内容并检查
EPERM
。检查
stat()
access()
不能保证后续操作不会返回EPERM。

在简单的情况下,两者在功能上是等效的。另外,
access()
也不会快得多,同样的数据结构(inode)也不会快得多


但是,如果在系统上使用访问控制列表(),access将处理这些列表,而您无法使用
stat
数据检查ACL。

这两个代码片段不相同,将产生实质性不同的结果

首先,您的stat调用只检查所有者的权限位。如果运行此代码的用户不拥有所讨论的文件,则这不是要检查的正确位集

其次,即使我们假设呼叫用户是所有者,我们也需要弄清楚“呼叫用户”是什么意思。就
open(2)
及其朋友而言,呼叫用户是返回的号码,即有效用户ID。这是open用来确定是否允许打开文件的。就
access(2)
而言,呼叫用户是
getuid(2)
返回的号码,即真实的用户ID。这是access用来确定是否报告成功的内容。真正的UID和有效的UID可能不同,特别是当运行启用了setuid位的二进制文件时,或者当程序员正在做一些特别聪明的事情时(可能是不明智的IMHO)

(同时,
stat()


最后,正如在多个答案中所指出的,这两个代码段都可能容易受到bug的攻击,这取决于您对结果所做的操作。总之,确定是否允许某个操作的最安全方法是尝试该操作并检查其是否失败。

您的代码有点错误<代码>访问(目录,R_OK&W_OK)
应该是
访问(目录,R_OK | W_OK)
。也没有理由计算
(stats.mode)和(0777)
;您可以直接使用
stats.mode
。也就是说,这些方法之间没有功能上的区别。如果您想要可移植代码,另一个问题是:在POSIX下,您需要验证当前用户是否特别拥有这些权限;您的测试仅检查目标上的权限,而不检查其是否适用于当前用户。在手册页中:“使用access()检查用户是否有权打开文件,例如,在实际使用open(2)打开文件之前创建一个安全漏洞,因为用户可能利用检查和打开文件之间的短时间间隔对其进行操作。”或者,如果您需要文件的统计信息,则
打开文件并对其使用
fstat
。至少你知道stat info是针对你持有句柄的同一个文件的。@Zan:除了检查读和/或写权限之外。。。如果
打开
成功,显然您至少已经有一个:-)。(编辑:好的,我想你可以用
O_SEARCH
打开一个目录。但是接下来我们将如何处理权限检查的结果呢?接受Adam的建议并简单地尝试所需的操作本身更有意义。)@Nemo:说得好。我在考虑其他的事情,比如大小或所有权,但对于读/写访问来说,这并不重要。
       // Using access():
    bool readAccessPermission = false; 
    bool writeAccessPermission = false;

    if (mode == 'r'){
            if (access(directory, R_OK) == 0)
                    readAccessPermission = true;                        
    }
    else{
            if (access(directory, R_OK && W_OK) == 0)
                    readAccessPermission = true;
                    writeAccessPermission = true;
    }


    // vs. using stat function
    // assume I already called stat(directory) and have the object


    bool readAccessPermission = false; 
    bool writeAccessPermission = false;

    var retmode = ((stats.mode) & (0777));

    if (modeString == 'r'){ 
        if ((retmode) & (consts.S_IRUSR)){
            readAccessPermission = false; 
        }    
    } 
    else{ 
        if ((retmode) & (consts.S_IRUSR)){
            readAccessPermission = true; 

            if ((retmode) & consts.S_IWUSR)){               
                writeAccessPermission = true; 
            }
        }
    }