plain C:用fopen()打开一个目录

我有一个程序打开一个文件,并检查其长度。

FILE* fd = fopen(argv[1], "rb"); fseek(fd, 0, SEEK_END); size_t flen = ftell(fd); if (flen == ((size_t)-1)) { printf("%s is a directory.\n", argv[1]); fclose(fd); exit(1); } 

现在,至less在Linux下, fopen()在打开目录时返回一个有效的文件描述符。 这导致查找操作返回-1 (或者,在64位系统上size_t是无符号的, 0xFFFFFFFF )。

不幸的是,在上面的代码( flen == ((size_t)-1) )中的条件不能捕捉到这种情况, flen == 0xFFFFFFFF也没有。 printf() – 使用%x ord %d作为格式string的命令显示比较的两边应具有相同的值。

为什么比较运算符以这样一种奇怪的方式运行,即使双方的types相同( size_t )? 我使用gcc 4.8.1作为编译器。

目录不存在于C99标准(或C2011标准)中。 因此,根据定义, fopen一个目录是特定于实现的还是未定义的行为。

fopen(3)可能会失败(给出一个NULL结果)。 fseek(3)也可能失败(通过返回-1)。 然后,你应该最好检查errno(3)或使用perror(3)

ftell被记录为返回一个long -1L失败。 在64位Linux上这是0xffffffffffffffff

你的代码应该是相反的

 FILE* fd = fopen(argv[1], "rb"); if (!fd) { perror(argv[1]); exit(EXIT_FAILURE); }; if (fseek(fd, 0, SEEK_END)<0) { perror("fseek"); exit(EXIT_FAILURE); }; long flen = ftell(fd); if (flen == -1L) { perror("ftell"); exit(EXIT_FAILURE); }; 

顺便说一句,在Linux / Debian / Sid / AMD64与libc-2.17和3.10.6内核,当argv[1]/tmp ; flen是LONG_MAX0x7fffffffffffffff

顺便说一下,在Linux上,目录是文件的特殊情况。 在文件路径上使用stat(2) (以及在fstat上使用fstat ,可能从某个FILE* fileno(3)获得)来了解更多关于某个文件的元数据,包括其“type”(通过它的模式)。 你需要opendir(3) , readdir(3)和closedir(3)来操作目录内容。 另见inode(7) 。

来自http://pubs.opengroup.org/onlinepubs/7908799/xsh/fopen.html

 The fopen() function will fail if: [EISDIR] The named file is a directory and mode requires write access. 

至少在Linux上,如果你试图fopen("dirname", "wb")你会得到一个EISDIR错误。 我也试过用d ——–访问权限的目录,我仍然得到EISDIR(而不是EACCES)。