微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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).

原文地址:https://www.jb51.cc/c/113627.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐