【问题标题】:Linux, C: access() not catching permission problems, or somethingLinux, C: access() 没有发现权限问题,或者什么
【发布时间】:2012-03-16 13:55:34
【问题描述】:

我正在编写一个程序来模仿find 的一些行为,它遍历目录树并在找到的文件上调用lstat 以确定它们的类型。真正的find 将忽略用户在该目录中没有 R 或 X 访问权限的文件。我似乎无法复制这种行为;即使执行此操作的代码位于检查access() 的块内,我的代码也会继续调用lstat 并获得非法搜索错误(这是我试图阻止的)。

我的第一个想法是,也许第二个 access() 调用应该在路径上而不是路径/文件名上,但这似乎也不起作用(而且它不是多余的吗?)

任何指导将不胜感激。

我的代码(为简洁起见,我删除了错误捕获和其他内容):

    void open_dir( char *dir, char *pattern, char type )
    {
        DIR *d;
        struct dirent *de;

        if ( access(dir, (R_OK | X_OK)) == 0 )
        {
            d = opendir(dir);

            while( ( de = readdir(d) ) )
                examine_de( de, dir, pattern, type );

            closedir(d);
        }
    }

    void examine_de( struct dirent *de, char *dir, char *pattern, char type )
    {
        char fn[ _POSIX_PATH_MAX ];
        strcpy(fn, dir);
        strcat(fn, "/");
        strcat(fn, de->d_name);

        if ( access(fn, (R_OK | X_OK)) == 0 )
        {
            struct stat buf;
            lstat(fn, &buf);
            //check pattern matches, etc., printf fn if appropriate
            if ( ( S_ISDIR(buf.st_mode) ) &&
                 ( strcmp(de->d_name, ".") != 0 ) &&
                 ( strcmp(de->d_name, "..") != 0 ) )
                open_dir(fn, pattern, type);
        }
        return;
    }

【问题讨论】:

    标签: c linux stat opendir


    【解决方案1】:

    lstat() 应该永远返回ESPIPE(非法搜索)。您确定不是另一个系统调用返回它,或者在成功lstat() 之后没有改变errno 值吗? (换句话说,错误可能实际上在您已省略的错误检查代码中)。

    也就是说,无论如何以这种方式使用access() 是没有意义的——它只会引入竞争条件(因为文件权限可能在access() 调用和opendir() / lstat() 调用之间发生变化) ,并没有任何收获。只需检查 opendir()lstat() 的返回值即可:

    void open_dir( char *dir, char *pattern, char type )
    {
        DIR *d;
        struct dirent *de;
    
        if (d = opendir(dir))
        {
            while( ( de = readdir(d) ) )
                examine_de( de, dir, pattern, type );
    
            closedir(d);
        }
    }
    
    void examine_de( struct dirent *de, char *dir, char *pattern, char type )
    {
        char fn[ _POSIX_PATH_MAX ];
        struct stat buf;
    
        strcpy(fn, dir);
        strcat(fn, "/");
        strcat(fn, de->d_name);
    
        if (lstat(fn, &buf) == 0)
        {
            //check pattern matches, etc., printf fn if appropriate
            if ( ( S_ISDIR(buf.st_mode) ) &&
                 ( strcmp(de->d_name, ".") != 0 ) &&
                 ( strcmp(de->d_name, "..") != 0 ) )
                open_dir(fn, pattern, type);
        }
        return;
    }
    

    这通常是正确的模式 - 与其检查操作是否可行,然后尝试操作,不如无条件尝试操作,然后检查失败的原因。

    【讨论】:

    • 您可能认为这是一个临时评论,但我发现在每个 perror 之后设置 errno = 0 会产生一些不同,尤其是在对 readdir 进行错误检查的情况下,因为 readdir在目录的末尾返回NULL以防出错,所以我的代码在继续之前检查是否errno == 0。但我当然也会牢记您对access 的警告——谢谢!
    • @SabrinaStar:您应该在readdir() 调用之前 立即设置errno = 0; - 这里的重点是不成功的调用设置errno,但成功的调用会离开@ 987654342@不变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2017-04-04
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多