我刚刚发现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*
,而不是文件名。仅测试文件名,然后再打开它是一种竞争条件。
答案 0 :(得分:1)
假设您使用的是基于POSIX的系统,请使用stat()
(如果您希望在调用sz
之前使用open()
中的文件名)或fstat()
(如果您希望在调用fd
之后使用描述符open()
来从OS获取文件状态结构。名为st_mode
的结构的成员可以与POSIX API S_ISDIR(st_mode)
一起使用,以查看文件是否为目录。
答案 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如果不是目录则失败。