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

我有一个打开文件并检查其长度的程序.
FILE* fd = fopen(argv[1],"rb");
fseek(fd,SEEK_END);
size_t flen = ftell(fd);
if (flen == ((size_t)-1)) {
    printf("%s is a directory.\n",argv[1]);
    fclose(fd);
    exit(1);
}

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

不幸的是,上面代码中的条件(flen ==((size_t)-1))没有捕获到这种情况,flen == 0xFFFFFFFF(编辑:应该是0xFFFFFFFFFFFFFFFF)也没有. printf() – 将%x或%d作为格式字符串的命令显示比较的两侧应具有相同的值.

为什么比较运算符表现得如此奇怪,即使双方属于同一类型(size_t)?我使用gcc 4.8.1作为编译器.

解决方法

C99标准(或C2011标准)中不存在目录.因此,根据定义,打开目录可以是特定于实现的行为,也可以是未定义的行为.

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

记录ftell返回长,-1L失败.在64位Linux上,这是0xffffffffffffffff.

你的代码应该是

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

BTW,在带有libc-2.17和3.10.6内核的Linux / Debian / Sid / AMD64上,当argv [1]为/ tmp时,代码运行正常;令人惊讶的是,flen是LONG_MAX,即0x7fffffffffffffff

顺便说一句,在Linux上,目录是文件的特例.在文件路径上使用stat(2)(和file descriptor上的fstat,可能是从某些FILE *获得fileno(3)),以了解更多关于某个文件的元数据,包括其“类型”(通过其模式).你想要opendir(3),readdir(3)& closedir(3)对目录内容进行操作.另见inode(7).

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...