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

How to tell if FILE* is referring to a directory?

刚刚发现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* 引用目录而不尝试从中读取的正确方法是什么?

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

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

有关详细信息,请参阅:http://man7.org/linux/man-pages/man2/stat.2.html

假设一个类似于 POSIX 的环境,如果您只有文件流 (FILE *fp),那么您可能只能使用 fileno() and 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…

正在检查 fcntl.h man 页面:

header shall define the following symbolic constants as file creation flags for use in the oflag value to open() and openat(). The values shall be bitwise-distinct and shall be suitable for use in #if preprocessing directives.

还有旗帜:

O_DIRECTORY Fail if not a directory.