如何判断FILE *是否指向目录?

时间:2018-12-13 16:40:25

标签: c file-descriptor stdio fcntl file-pointer

我刚刚发现FILE*不仅可以引用常规文件,还可以引用目录。如果是后者,fread将失败,并且errno设置为21 (Is a directory)

可以测试最低再现性here

#include <stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>

int main() {
    char const* sz = ".";

    int fd = open(sz, O_RDONLY | O_NOFOLLOW); // all cleanup omitted for brevity
    FILE* file = fdopen(fd, "rb");
    // I would like to test in this line if it is a directory

    char buffer[21];
    int const n = fread(buffer, 1, 20, file);
    if (0 < n) {
        buffer[n] = 0;
        printf(buffer);
    } else {
        printf("Error %d", errno); // 21 = Is a directory
    }
}

什么是早发现我的FILE*引用目录而不尝试读取该目录的正确方法?

编辑以排斥重复的标志: 我想测试FILE*,而不是文件名。仅测试文件名,然后再打开它是一种竞争条件。

3 个答案:

答案 0 :(得分:1)

假设您使用的是基于POSIX的系统,请使用stat()(如果您希望在调用sz之前使用open()中的文件名)或fstat()(如果您希望在调用fd之后使用描述符open()来从OS获取文件状态结构。名为st_mode的结构的成员可以与POSIX API S_ISDIR(st_mode)一起使用,以查看文件是否为目录。

有关更多信息,请参见:http://man7.org/linux/man-pages/man2/stat.2.html

答案 1 :(得分:1)

假设是类似POSIX的环境,如果只有文件流(FILE *fp),则可能会减少使用fileno()fstat()

#include <sys/stat.h>


struct stat sb;
if (fstat(fileno(fp), &sb) != 0)
    …oops…
if (S_ISDIR(sb.st_mode))
    …it is a directory…
else
    …it is not a directory…

答案 2 :(得分:0)

检查fcntl.h LIKE页:

  

标头应将以下符号常量定义为   在open()和oflag值中使用的文件创建标志   openat()。这些值应按位区分并应适当   用于#if预处理指令中。

还有标志:

  

O_DIRECTORY如果不是目录则失败。